Zelda Classic Coverage Report


Directory: src/
File: src/zc/hero.cpp
Date: 2022-11-29 04:45:57
Exec Total Coverage
Lines: 3669 15651 23.4%
Functions: 143 315 45.4%
Branches: 2481 19518 12.7%

Line Branch Exec Source
1 //--------------------------------------------------------
2 //--------------------------------------------------------
3 //--------------------------------------------------------
4 // Zelda Classic
5 // by Jeremy Craner, 1999-2000
6 //
7 // hero.cpp
8 //
9 // Hero's class: HeroClass
10 // Handles a lot of game play stuff as well as Hero's
11 // movement, attacking, etc.
12 //
13 //--------------------------------------------------------
14
15 #ifndef __GTHREAD_HIDE_WIN32API
16 11 #define __GTHREAD_HIDE_WIN32API 1
17 #endif //prevent indirectly including windows.h
18
19 #include "precompiled.h" //always first
20
21 #include <string.h>
22 #include <set>
23 #include <stdio.h>
24
25 #include "hero.h"
26 #include "guys.h"
27 #include "subscr.h"
28 #include "zc_subscr.h"
29 #include "decorations.h"
30 #include "gamedata.h"
31 #include "zc_custom.h"
32 #include "title.h"
33 #include "ffscript.h"
34 #include "drawing.h"
35 #include "combos.h"
36 #include "base/zc_math.h"
37 #include "user_object.h"
38 #include "slopes.h"
39 extern FFScript FFCore;
40 extern word combo_doscript[176];
41 extern byte itemscriptInitialised[256];
42 extern HeroClass Hero;
43 extern ZModule zcm;
44 extern zcmodule moduledata;
45 extern refInfo playerScriptData;
46 #include "zscriptversion.h"
47 #include "particles.h"
48 #include <fmt/format.h>
49
50 extern refInfo itemScriptData[256];
51 extern refInfo itemCollectScriptData[256];
52 extern int32_t item_stack[256][MAX_SCRIPT_REGISTERS];
53 extern int32_t item_collect_stack[256][MAX_SCRIPT_REGISTERS];
54 extern refInfo *ri; //= NULL;
55 extern int32_t(*stack)[MAX_SCRIPT_REGISTERS];
56 extern byte dmapscriptInitialised;
57 extern word item_doscript[256];
58 extern word item_collect_doscript[256];
59 extern portal* mirror_portal;
60 using std::set;
61
62 extern int32_t skipcont;
63
64 extern int32_t draw_screen_clip_rect_x1;
65 extern int32_t draw_screen_clip_rect_x2;
66 extern int32_t draw_screen_clip_rect_y1;
67 extern int32_t draw_screen_clip_rect_y2;
68 extern word global_wait;
69 extern bool player_waitdraw;
70 extern bool dmap_waitdraw;
71 extern bool passive_subscreen_waitdraw;
72 extern bool active_subscreen_waitdraw;
73
74 int32_t hero_count = -1;
75 int32_t hero_animation_speed = 1; //lower is faster animation
76 int32_t z3step = 2;
77 11 static zfix hero_newstep(1.5);
78 11 static zfix hero_newstep_diag(1.5);
79 bool did_scripta=false;
80 bool did_scriptb=false;
81 bool did_scriptl=false;
82 byte lshift = 0;
83 int32_t dowpn = -1;
84 int32_t directItem = -1; //Is set if Hero is currently using an item directly
85 int32_t directItemA = -1;
86 int32_t directItemB = -1;
87 int32_t directItemX = -1;
88 int32_t directItemY = -1;
89 int32_t directWpn = -1;
90 int32_t whistleitem=-1;
91 extern word g_doscript;
92 extern word player_doscript;
93 extern word dmap_doscript;
94 extern word passive_subscreen_doscript;
95 extern byte epilepsyFlashReduction;
96 extern int32_t script_hero_cset;
97
98 void playLevelMusic();
99
100 extern particle_list particles;
101
102 byte lsteps[8] = { 1, 1, 2, 1, 1, 2, 1, 1 };
103
104 #define CANFORCEFACEUP (get_bit(quest_rules,qr_SIDEVIEWLADDER_FACEUP)!=0 && dir!=up && (action==walking || action==none))
105 #define NO_GRIDLOCK (get_bit(quest_rules, qr_DISABLE_4WAY_GRIDLOCK))
106 #define SWITCHBLOCK_STATE (switchblock_z<0?switchblock_z:(switchblock_z+z+fakez < 0 ? zslongToFix(2147483647) : switchblock_z+z+fakez))
107 #define FIXED_Z3_ANIMATION ((zinit.heroAnimationStyle==las_zelda3||zinit.heroAnimationStyle==las_zelda3slow)&&!get_bit(quest_rules,qr_BROKEN_Z3_ANIMATION))
108
109 4809 static inline bool on_sideview_slope(int32_t x, int32_t y, int32_t oldx, int32_t oldy)
110 {
111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4809 times.
4809 if(check_new_slope(x, y+1, 16, 16, oldx, oldy) < 0) return true;
112 4809 return false;
113 4809 }
114
115 1603 static inline bool platform_fallthrough(bool doslopecheck = true)
116 {
117
3/6
✓ Branch 0 taken 1603 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1603 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1603 times.
✗ Branch 5 not taken.
4549 return (doslopecheck && !on_sideview_slope(Hero.x, Hero.y,Hero.old_x,Hero.old_y) && (on_sideview_slope(Hero.x,Hero.y+1,Hero.old_x,Hero.old_y) || on_sideview_slope(Hero.x, Hero.y + 2, Hero.old_x, Hero.old_y)) && getInput(btnDown, false, get_bit(quest_rules,qr_SIDEVIEW_FALLTHROUGH_USES_DRUNK)!=0))
118
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 130 times.
1603 || (getInput(btnDown, false, get_bit(quest_rules,qr_SIDEVIEW_FALLTHROUGH_USES_DRUNK)!=0) && get_bit(quest_rules,qr_DOWN_FALL_THROUGH_SIDEVIEW_PLATFORMS))
119
3/6
✓ Branch 0 taken 1343 times.
✓ Branch 1 taken 1473 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1603 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
260 || (Hero.jumping < 0 && getInput(btnDown, false, get_bit(quest_rules,qr_SIDEVIEW_FALLTHROUGH_USES_DRUNK)!=0) && get_bit(quest_rules,qr_DOWNJUMP_FALL_THROUGH_SIDEVIEW_PLATFORMS));
120 }
121
122 static inline bool on_sideview_solid(int32_t x, int32_t y, bool ignoreFallthrough = false, int32_t slopesmisc = 0)
123 {
124 if(slopesmisc != 1 && check_slope(x, y+1, 16, 16, (slopesmisc == 3)) < 0) return true;
125 if(slopesmisc == 2) return false;
126 if (_walkflag(x+4,y+16,1) || _walkflag(x+12,y+16,1)) return true;
127 if (y>=160 && currscr>=0x70 && !(tmpscr->flags2&wfDOWN)) return true;
128 if (platform_fallthrough() && !ignoreFallthrough) return false;
129 if(slopesmisc != 1 && check_slope(x, y+1, 16, 16) < 0) return true;
130 if (y%16==0 && (checkSVLadderPlatform(x+4,y+16) || checkSVLadderPlatform(x+12,y+16)))
131 return true;
132 return false;
133 }
134
135 1888 static inline bool on_sideview_solid_oldpos(int32_t x, int32_t y, int32_t oldx, int32_t oldy, bool ignoreFallthrough = false, int32_t slopesmisc = 0)
136 {
137
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if(slopesmisc != 1 && check_new_slope(x, y+1, 16, 16, oldx, oldy, (slopesmisc == 3)) < 0) return true;
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(slopesmisc == 2) return false;
139
4/4
✓ Branch 0 taken 1648 times.
✓ Branch 1 taken 240 times.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 1604 times.
1888 if (_walkflag(x+4,y+16,1) || _walkflag(x+12,y+16,1)) return true;
140
5/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1602 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1604 if (y>=160 && currscr>=0x70 && !(tmpscr->flags2&wfDOWN)) return true;
141
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1603 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1603 if (platform_fallthrough() && !ignoreFallthrough) return false;
142
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1603 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1603 if (slopesmisc != 1 && check_new_slope(x, y + 1, 16, 16, oldx, oldy) < 0) return true;
143
4/6
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 1010 times.
✓ Branch 2 taken 593 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 593 times.
1603 if (y%16==0 && (checkSVLadderPlatform(x+4,y+16) || checkSVLadderPlatform(x+12,y+16)))
144 return true;
145 1603 return false;
146 1888 }
147
148
149 4934 bool usingActiveShield(int32_t itmid)
150 {
151
2/2
✓ Branch 0 taken 3838 times.
✓ Branch 1 taken 1096 times.
4934 switch(Hero.action) //filter allowed actions
152 {
153 case none: case walking: case rafting:
154 case gothit: case swimhit:
155 3838 break;
156 1096 default: return false;
157 }
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3838 times.
3838 if(itmid < 0)
159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3838 times.
3838 itmid = (Hero.active_shield_id < 0
160 3838 ? current_item_id(itype_shield,true,true) : Hero.active_shield_id);
161
1/2
✓ Branch 0 taken 3838 times.
✗ Branch 1 not taken.
3838 if(itmid < 0) return false;
162
1/2
✓ Branch 0 taken 3838 times.
✗ Branch 1 not taken.
3838 if(!checkitem_jinx(itmid)) return false;
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3838 times.
3838 if(!(itemsbuf[itmid].flags & ITEM_FLAG9)) return false;
164 if(!isItmPressed(itmid)) return false;
165 return (checkbunny(itmid) && checkmagiccost(itmid));
166 4934 }
167 3131 int32_t getCurrentShield(bool requireActive)
168 {
169
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3131 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3131 if(Hero.active_shield_id > -1 && usingActiveShield(Hero.active_shield_id))
170 return Hero.active_shield_id;
171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3131 times.
3131 if(!requireActive) return current_item_id(itype_shield);
172 return -1;
173 3131 }
174 int32_t getCurrentActiveShield()
175 {
176 int32_t id = Hero.active_shield_id;
177 if(id > -1 && usingActiveShield(id))
178 return id;
179 return -1;
180 }
181 1888 int32_t refreshActiveShield()
182 {
183 1888 int32_t id = -1;
184
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(DrunkcBbtn())
185 {
186 itemdata const& dat = itemsbuf[Bwpn&0xFFF];
187 if(dat.family == itype_shield && (dat.flags & ITEM_FLAG9))
188 {
189 id = Bwpn&0xFFF;
190 }
191 }
192
3/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1742 times.
✓ Branch 3 taken 146 times.
1888 if(id < 0 && DrunkcAbtn())
193 {
194 146 itemdata const& dat = itemsbuf[Awpn&0xFFF];
195
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
146 if(dat.family == itype_shield && (dat.flags & ITEM_FLAG9))
196 {
197 id = Awpn&0xFFF;
198 }
199 146 }
200
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
1888 if(id < 0 && DrunkcEx1btn())
201 {
202 itemdata const& dat = itemsbuf[Xwpn&0xFFF];
203 if(dat.family == itype_shield && (dat.flags & ITEM_FLAG9))
204 {
205 id = Xwpn&0xFFF;
206 }
207 }
208
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
1888 if(id < 0 && DrunkcEx2btn())
209 {
210 itemdata const& dat = itemsbuf[Ywpn&0xFFF];
211 if(dat.family == itype_shield && (dat.flags & ITEM_FLAG9))
212 {
213 id = Ywpn&0xFFF;
214 }
215 }
216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(!usingActiveShield(id))
217 1888 return -1;
218 return id;
219 1888 }
220 static bool is_immobile()
221 {
222 if(!get_bit(quest_rules, qr_NEW_HERO_MOVEMENT))
223 return false;
224 zfix rate(Hero.steprate);
225 int32_t shieldid = getCurrentActiveShield();
226 if(shieldid > -1)
227 {
228 itemdata const& shield = itemsbuf[shieldid];
229 if(shield.flags & ITEM_FLAG10) //Change Speed flag
230 {
231 zfix perc = shield.misc7;
232 perc /= 100;
233 if(perc < 0)
234 perc = (perc*-1)+1;
235 rate = (rate * perc) + shield.misc8;
236 }
237 }
238 return rate != 0;
239 }
240
241 1888 bool HeroClass::isStanding(bool forJump)
242 {
243
3/14
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1888 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
1888 bool st = (z==0 && fakez==0 && !(isSideViewHero() && !on_sideview_solid_oldpos(x,y,old_x,old_y) && !ladderx && !laddery && !getOnSideviewLadder()) && hoverclk==0);
244
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(!st) return false;
245 1888 int32_t val = check_pitslide();
246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(val == -2) return false;
247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(val == -1) return true;
248 return forJump;
249 1888 }
250 bool HeroClass::isLifting()
251 {
252 if(lift_wpn) return true;
253 return false;
254 }
255
256 6 void HeroClass::set_respawn_point(bool setwarp)
257 {
258
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if(setwarp)
259 {
260 3 warpx = x;
261 3 warpy = y;
262 3 raftwarpx = x;
263 3 raftwarpy = y;
264 3 }
265
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if(!get_bit(quest_rules,qr_OLD_RESPAWN_POINTS))
266 {
267 switch(action)
268 {
269 case none: case walking:
270 break;
271 default:
272 return; //Not a 'safe action'
273 }
274 if(z > 0 || fakez > 0 || hoverclk) return; //in air
275 if(check_pitslide(true) != -1) return; //On a pit
276
277 { //Check water
278 int32_t water = 0;
279 int32_t types[4] = {0};
280 int32_t x1 = x+4, x2 = x+11,
281 y1 = y+9, y2 = y+15;
282 if (get_bit(quest_rules, qr_SMARTER_WATER))
283 {
284 if (iswaterex(0, currmap, currscr, -1, x1, y1, true, false) &&
285 iswaterex(0, currmap, currscr, -1, x1, y2, true, false) &&
286 iswaterex(0, currmap, currscr, -1, x2, y1, true, false) &&
287 iswaterex(0, currmap, currscr, -1, x2, y2, true, false)) water = iswaterex(0, currmap, currscr, -1, (x2+x1)/2,(y2+y1)/2, true, false);
288 }
289 else
290 {
291 types[0] = COMBOTYPE(x1,y1);
292
293 if(MAPFFCOMBO(x1,y1))
294 types[0] = FFCOMBOTYPE(x1,y1);
295
296 types[1] = COMBOTYPE(x1,y2);
297
298 if(MAPFFCOMBO(x1,y2))
299 types[1] = FFCOMBOTYPE(x1,y2);
300
301 types[2] = COMBOTYPE(x2,y1);
302
303 if(MAPFFCOMBO(x2,y1))
304 types[2] = FFCOMBOTYPE(x2,y1);
305
306 types[3] = COMBOTYPE(x2,y2);
307
308 if(MAPFFCOMBO(x2,y2))
309 types[3] = FFCOMBOTYPE(x2,y2);
310
311 int32_t typec = COMBOTYPE((x2+x1)/2,(y2+y1)/2);
312 if(MAPFFCOMBO((x2+x1)/2,(y2+y1)/2))
313 typec = FFCOMBOTYPE((x2+x1)/2,(y2+y1)/2);
314
315 if(combo_class_buf[types[0]].water && combo_class_buf[types[1]].water &&
316 combo_class_buf[types[2]].water && combo_class_buf[types[3]].water && combo_class_buf[typec].water)
317 water = typec;
318 }
319 if(water > 0)
320 {
321 return;
322 }
323 } //End check water
324
325 int poses[4] = {
326 COMBOPOS(x,y+(bigHitbox?0:8)),
327 COMBOPOS(x,y+15),
328 COMBOPOS(x+15,y+(bigHitbox?0:8)),
329 COMBOPOS(x+15,y+15)
330 };
331 for(auto pos : poses)
332 {
333 if(HASFLAG_ANY(mfUNSAFEGROUND, pos)) //"Unsafe Ground" flag touching the player
334 return;
335 }
336 }
337 6 respawn_x = x;
338 6 respawn_y = y;
339 6 respawn_scr = currscr;
340 6 respawn_dmap = currdmap;
341 6 }
342
343 void HeroClass::go_respawn_point()
344 {
345 x = respawn_x;
346 y = respawn_y;
347 can_mirror_portal = false; //incase entry is on a portal!
348 warpx=x;
349 warpy=y;
350 raftwarpx = x;
351 raftwarpy = y;
352 trySideviewLadder(); //Cling to ladder automatically
353
354 if(get_bit(quest_rules, qr_OLD_RESPAWN_POINTS))
355 return; //No cross-screen return
356
357 if(currdmap != respawn_dmap || currscr != respawn_scr)
358 {
359 FFCore.warp_player(wtIWARP, respawn_dmap, respawn_scr,
360 -1, -1, 0, 0, warpFlagNOSTEPFORWARD|warpFlagDONTKILLMUSIC, -1);
361 }
362 }
363
364 3 void HeroClass::trySideviewLadder()
365 {
366
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if(canSideviewLadder() && !on_sideview_solid_oldpos(x,y,old_x,old_y))
367 setOnSideviewLadder(true);
368 3 }
369
370 8234 bool HeroClass::can_pitfall(bool ignore_hover)
371 {
372
15/30
✓ Branch 0 taken 8234 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8234 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8234 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8234 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8234 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8234 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 8234 times.
✓ Branch 14 taken 8234 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8234 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 8234 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 8234 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 8234 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 8234 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 8234 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 8234 times.
8234 return (!(isSideViewGravity()||action==rafting||z>0||fakez>0||fall<0||fakefall<0||(hoverclk && !ignore_hover)||inlikelike||inwallm||pull_hero||toogam||(ladderx||laddery)||getOnSideviewLadder()||drownclk||!(moveflags & FLAG_CAN_PITFALL)));
373 }
374
375 1140 int32_t HeroClass::DrunkClock()
376 {
377 1140 return drunkclk;
378 }
379 void HeroClass::setDrunkClock(int32_t newdrunkclk)
380 {
381 drunkclk=newdrunkclk;
382 }
383
384 int32_t HeroClass::StunClock()
385 {
386 return lstunclock;
387 }
388 void HeroClass::setStunClock(int32_t v)
389 {
390 lstunclock=v;
391 }
392
393 3716 int32_t HeroClass::BunnyClock()
394 {
395 3716 return lbunnyclock;
396 }
397 void HeroClass::setBunnyClock(int32_t v)
398 {
399 lbunnyclock=v;
400 }
401
402
9/18
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 11 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11 times.
✗ Branch 17 not taken.
44 HeroClass::HeroClass() : sprite()
403 33 {
404 11 lift_wpn = nullptr;
405
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 init();
406 22 }
407
408 //2.6
409
410 //Stop the subscreen from falling. -Z
411
412 bool HeroClass::stopSubscreenFalling(){
413 return preventsubscreenfalling;
414 }
415
416 void HeroClass::stopSubscreenFalling(bool v){
417 preventsubscreenfalling = v;
418 }
419
420
421 //Set the button items by brute force
422
423 void HeroClass::setAButtonItem(int32_t itmslot){
424 game->awpn = itmslot;
425 }
426
427 void HeroClass::setBButtonItem(int32_t itmslot){
428 game->bwpn = itmslot;
429 }
430
431 1888 void HeroClass::ClearhitHeroUIDs()
432 { //Why the flidd doesn't this work?! Clearing this to 0 in a way that doesn't demolish script access is impossible. -Z
433 //All I want, is to clear it at the end of a frame, or at the start of a frame, so that if it changes to non-0
434 //that a script can read it before Waitdraw(). --I want it to go stale at the end of a frame.
435 //I suppose I will need to do this inside the script engine, and not the game_loop() ? -Z
436 //THis started out as a simple clear to 0 of lastHitBy[n], but that did not work:
437 //I added the second element to this, so that I could store the frame on which the hit is recorded, and
438 //clear it on the next frame, but that had the SAME outcome.
439 //Where and how can I clear a value at the end of every frame, so that:
440 // 1. If set by internal mecanics, it has its value that you can read by script, before waitdraw--this part works at present.
441 // 2. FFCs can read it before Waitframe. --same.
442 // 3. After Waitframe(), it is wiped by the ZC Engine to 0. --I cannot get this to happen without breaking 1 and 2.
443
2/2
✓ Branch 0 taken 15104 times.
✓ Branch 1 taken 1888 times.
16992 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED_PLAYER; q++ )
444 {
445 /*
446 if ( lastHitBy[q][1] == (frame-1) ) //Verify if this is needed at all now.
447 {
448 //Z_scripterrlog("frame is: %d\n", frame);
449 //Z_scripterrlog("Player->HitBy frame is: %d\n", lastHitBy[q][1]);
450 lastHitBy[q][0] = 0;
451 }
452 */
453 15104 lastHitBy[q][0] = 0;
454 15104 }
455 1888 }
456
457 void HeroClass::sethitHeroUID(int32_t type, int32_t screen_index)
458 {
459 lastHitBy[type][0] = screen_index;
460 //lastHitBy[type][1] = frame;
461 /* Let's figure out how to clear this...
462 if ( global_wait ) lastHitBy[type] = screen_index;
463 else lastHitBy[type] = 0;
464 //No, we clear it in Zelda.cpp, with this:
465 if(global_wait)
466 {
467 ZScriptVersion::RunScript(SCRIPT_GLOBAL, GLOBAL_SCRIPT_GAME, GLOBAL_SCRIPT_GAME);
468 global_wait=false;
469 }
470
471
472 draw_screen(tmpscr);
473
474 //clear Hero's last hits
475 //for ( int32_t q = 0; q < 4; q++ ) Hero.sethitHeroUID(q, 0);
476
477 */
478
479 }
480
481 int32_t HeroClass::gethitHeroUID(int32_t type)
482 {
483 return lastHitBy[type][0];
484 }
485
486 void HeroClass::set_defence(int32_t type, int32_t v)
487 {
488 defence[type] = v;
489 }
490
491 int32_t HeroClass::get_defence(int32_t type)
492 {
493 return defence[type];
494 }
495
496
497 //Set Hero;s hurt sfx
498 void HeroClass::setHurtSFX(int32_t sfx)
499 {
500 QMisc.miscsfx[sfxHURTPLAYER] = sfx;
501 }
502 int32_t HeroClass::getHurtSFX()
503 {
504 return QMisc.miscsfx[sfxHURTPLAYER];
505 }
506
507 bool HeroClass::getDiagMove()
508 {
509 return diagonalMovement;
510 }
511 void HeroClass::setDiagMove(bool newdiag)
512 {
513 diagonalMovement=newdiag;
514 }
515 bool HeroClass::getBigHitbox()
516 {
517 return bigHitbox;
518 }
519 15 void HeroClass::setBigHitbox(bool newbigHitbox)
520 {
521 15 bigHitbox=newbigHitbox;
522 15 syofs = bigHitbox?0:8;
523 15 sysz_ofs = bigHitbox?0:-8;
524 15 }
525 int32_t HeroClass::getStepRate()
526 {
527 return steprate;
528 }
529 void HeroClass::setStepRate(int32_t newrate)
530 {
531 steprate = newrate;
532 }
533 int32_t HeroClass::getSwimUpRate()
534 {
535 return game->get_sideswim_up();
536 }
537 void HeroClass::setSwimUpRate(int32_t newrate)
538 {
539 game->set_sideswim_up(newrate);
540 }
541 int32_t HeroClass::getSwimSideRate()
542 {
543 return game->get_sideswim_side();
544 }
545 void HeroClass::setSwimSideRate(int32_t newrate)
546 {
547 game->set_sideswim_side(newrate);
548 }
549 int32_t HeroClass::getSwimDownRate()
550 {
551 return game->get_sideswim_down();
552 }
553 void HeroClass::setSwimDownRate(int32_t newrate)
554 {
555 game->set_sideswim_down(newrate);
556 }
557
558
559 //void HeroClass::herostep() { lstep = lstep<(BSZ?27:11) ? lstep+1 : 0; }
560 1348 void HeroClass::herostep()
561 {
562
2/2
✓ Branch 0 taken 1231 times.
✓ Branch 1 taken 117 times.
1348 lstep = lstep<((zinit.heroAnimationStyle==las_bszelda)?27:11) ? lstep+1 : 0;
563 //need to run all global/hero/dmap scripts here?
564 1348 }
565
566 bool is_moving()
567 {
568 return DrunkUp()||DrunkDown()||DrunkLeft()||DrunkRight();
569 }
570
571 // called by ALLOFF()
572 22 void HeroClass::resetflags(bool all)
573 {
574 22 refilling=REFILL_NONE;
575 22 inwallm=false;
576 22 inlikelike=blowcnt=whirlwind=specialcave=hclk=fairyclk=refill_why=didstuff=0;
577 22 usecounts.clear();
578
579
3/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 19 times.
22 if(swordclk>0 || all)
580 {
581 3 swordclk=0;
582 3 verifyAWpn();
583 3 }
584
3/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 19 times.
22 if(itemclk>0 || all)
585 3 itemclk=0;
586
587
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 3 times.
22 if(all)
588 {
589 3 NayrusLoveShieldClk=0;
590
591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(nayruitem != -1)
592 {
593 stop_sfx(itemsbuf[nayruitem].usesound);
594 stop_sfx(itemsbuf[nayruitem].usesound+1);
595 }
596
597 3 nayruitem = -1;
598 3 hoverclk=jumping=0;
599 3 hoverflags = 0;
600 3 }
601 22 damageovertimeclk = 0;
602 22 newconveyorclk = 0;
603 22 switchhookclk = switchhookstyle = switchhookarg = switchhookmaxtime = 0;
604
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 154 times.
176 for(auto q = 0; q < 7; ++q)
605 154 hooked_undercombos[q] = -1;
606 22 hopclk=0;
607 22 hopdir=-1;
608 22 attackclk=0;
609 22 stomping=false;
610 22 reset_swordcharge();
611 22 diveclk=drownclk=drownCombo=0;
612 22 action=none; FFCore.setHeroAction(none);
613 22 conveyor_flags=0;
614 22 magiccastclk=0;
615 22 magicitem=-1;
616 22 }
617
618 //Can use this for Hero->Stun. -Z
619 1 void HeroClass::Freeze()
620 {
621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (action != inwind)
622 {
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (IsSideSwim()) {action=sideswimfreeze; FFCore.setHeroAction(sideswimfreeze);}
624 1 else {action=freeze; FFCore.setHeroAction(freeze);}
625 // also cancel Hero's attack
626 1 attackclk = 0;
627 1 }
628 1 }
629 15 void HeroClass::unfreeze()
630 {
631
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
15 if(action==freeze && fairyclk<1) { action=none; FFCore.setHeroAction(none); }
632
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
15 if(action==sideswimfreeze && fairyclk<1) { action=sideswimming; FFCore.setHeroAction(sideswimming); }
633 15 }
634
635 void HeroClass::Drown(int32_t state)
636 {
637 // Hero should never drown if the ladder is out
638 if(ladderx+laddery)
639 return;
640
641 drop_liftwpn();
642 switch(state)
643 {
644 case 1:
645 action=lavadrowning; FFCore.setHeroAction(lavadrowning);
646 attackclk=0;
647 attack=wNone;
648 attackid=-1;
649 reset_swordcharge();
650 drownclk=64;
651 z=fakez=fall=fakefall=0;
652 break;
653
654
655 default:
656 {
657 if (isSideViewHero() && get_bit(quest_rules,qr_SIDESWIM)){action=sidedrowning; FFCore.setHeroAction(sidedrowning);}
658 else {action=drowning; FFCore.setHeroAction(drowning);}
659 attackclk=0;
660 attack=wNone;
661 attackid=-1;
662 reset_swordcharge();
663 drownclk=64;
664 z=fakez=fall=fakefall=0;
665 break;
666 }
667 }
668
669 }
670
671 1 void HeroClass::finishedmsg()
672 {
673 //these are to cancel out any keys that Hero may
674 //be pressing so he doesn't attack at the end of
675 //a message if he was scrolling through it quickly.
676 1 rAbtn();
677 1 rBbtn();
678 1 unfreeze();
679
680
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
2 if(action == landhold1 ||
681
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 action == landhold2 ||
682
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 action == waterhold1 ||
683
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 action == waterhold2 ||
684
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 action == sidewaterhold1 ||
685 1 action == sidewaterhold2)
686 {
687 holdclk = 1;
688 }
689 1 }
690 void HeroClass::setEaten(int32_t i)
691 {
692 inlikelike=i;
693 }
694 int32_t HeroClass::getEaten()
695 {
696 return inlikelike;
697 }
698 149 zfix HeroClass::getX()
699 {
700 149 return x;
701 }
702 7 zfix HeroClass::getY()
703 {
704 7 return y;
705 }
706 10849 zfix HeroClass::getZ()
707 {
708 10849 return z;
709 }
710 6095 zfix HeroClass::getFakeZ()
711 {
712 6095 return fakez;
713 }
714 zfix HeroClass::getFall()
715 {
716 return fall;
717 }
718 zfix HeroClass::getFakeFall()
719 {
720 return fakefall;
721 }
722 zfix HeroClass::getXOfs()
723 {
724 return xofs;
725 }
726 zfix HeroClass::getYOfs()
727 {
728 return yofs;
729 }
730 void HeroClass::setXOfs(int32_t newxofs)
731 {
732 xofs=newxofs;
733 }
734 void HeroClass::setYOfs(int32_t newyofs)
735 {
736 yofs=newyofs;
737 }
738 int32_t HeroClass::getHXOfs()
739 {
740 return hxofs;
741 }
742 int32_t HeroClass::getHYOfs()
743 {
744 return hyofs;
745 }
746 int32_t HeroClass::getHXSz()
747 {
748 return hxsz;
749 }
750 int32_t HeroClass::getHYSz()
751 {
752 return hysz;
753 }
754 128 zfix HeroClass::getClimbCoverX()
755 {
756 128 return climb_cover_x;
757 }
758 128 zfix HeroClass::getClimbCoverY()
759 {
760 128 return climb_cover_y;
761 }
762 int32_t HeroClass::getLadderX()
763 {
764 return ladderx;
765 }
766 int32_t HeroClass::getLadderY()
767 {
768 return laddery;
769 }
770
771 void HeroClass::setX(int32_t new_x)
772 {
773 zfix dx=new_x-x;
774 if(Lwpns.idFirst(wHookshot)>-1)
775 {
776 Lwpns.spr(Lwpns.idFirst(wHookshot))->x+=dx;
777 hs_startx+=(int32_t)dx;
778 }
779
780 if(Lwpns.idFirst(wHSHandle)>-1)
781 {
782 Lwpns.spr(Lwpns.idFirst(wHSHandle))->x+=dx;
783 }
784
785 if(chainlinks.Count()>0)
786 {
787 for(int32_t j=0; j<chainlinks.Count(); j++)
788 {
789 chainlinks.spr(j)->x+=dx;
790 }
791 }
792
793 x=new_x;
794
795 // A kludge
796 if(!diagonalMovement && dir<=down)
797 is_on_conveyor=true;
798 }
799
800 void HeroClass::setY(int32_t new_y)
801 {
802 zfix dy=new_y-y;
803 if(Lwpns.idFirst(wHookshot)>-1)
804 {
805 Lwpns.spr(Lwpns.idFirst(wHookshot))->y+=dy;
806 hs_starty+=(int32_t)dy;
807 }
808
809 if(Lwpns.idFirst(wHSHandle)>-1)
810 {
811 Lwpns.spr(Lwpns.idFirst(wHSHandle))->y+=dy;
812 }
813
814 if(chainlinks.Count()>0)
815 {
816 for(int32_t j=0; j<chainlinks.Count(); j++)
817 {
818 chainlinks.spr(j)->y+=dy;
819 }
820 }
821
822 y=new_y;
823
824 // A kludge
825 if(!diagonalMovement && dir>=left)
826 is_on_conveyor=true;
827 }
828
829 void HeroClass::setZ(int32_t new_z)
830 {
831 if(isSideViewHero())
832 return;
833
834 if(z==0 && new_z > 0)
835 {
836 switch(action)
837 {
838 case swimming:
839 {
840 diveclk=0;
841 action=walking; FFCore.setHeroAction(walking);
842 break;
843 }
844
845 case waterhold1:
846 {
847 action=landhold1; FFCore.setHeroAction(landhold1);
848 break;
849 }
850
851 case waterhold2:
852 {
853 action=landhold2; FFCore.setHeroAction(landhold2);
854 break;
855 }
856
857 default:
858 if(charging) //!DIMITODO: Let Hero jump while charging sword
859 {
860 reset_swordcharge();
861 attackclk=0;
862 }
863
864 break;
865 }
866 }
867
868 z=(new_z>0 ? new_z : 0);
869 }
870
871 void HeroClass::setFakeZ(int32_t new_z)
872 {
873 if(isSideViewHero())
874 return;
875
876 if(fakez==0 && new_z > 0)
877 {
878 switch(action)
879 {
880 case swimming:
881 {
882 diveclk=0;
883 action=walking; FFCore.setHeroAction(walking);
884 break;
885 }
886
887 case waterhold1:
888 {
889 action=landhold1; FFCore.setHeroAction(landhold1);
890 break;
891 }
892
893 case waterhold2:
894 {
895 action=landhold2; FFCore.setHeroAction(landhold2);
896 break;
897 }
898
899 default:
900 if(charging) //!DIMITODO: Let Hero jump while charging sword
901 {
902 reset_swordcharge();
903 attackclk=0;
904 }
905
906 break;
907 }
908 }
909
910 fakez=(new_z>0 ? new_z : 0);
911 }
912
913 void HeroClass::setXfix(zfix new_x)
914 {
915 //Z_scripterrlog("setxdbl: %f\n",new_x);
916 zfix dx=new_x-x;
917 if(Lwpns.idFirst(wHookshot)>-1)
918 {
919 Lwpns.spr(Lwpns.idFirst(wHookshot))->x+=dx;
920 hs_startx+=(int32_t)dx;
921 }
922
923 if(Lwpns.idFirst(wHSHandle)>-1)
924 {
925 Lwpns.spr(Lwpns.idFirst(wHSHandle))->x+=dx;
926 }
927
928 if(chainlinks.Count()>0)
929 {
930 for(int32_t j=0; j<chainlinks.Count(); j++)
931 {
932 chainlinks.spr(j)->x+=dx;
933 }
934 }
935
936 x=new_x;
937
938 // A kludge
939 if(!diagonalMovement && dir<=down)
940 is_on_conveyor=true;
941 }
942
943 void HeroClass::setYfix(zfix new_y)
944 {
945 zfix dy=new_y-y;
946 if(Lwpns.idFirst(wHookshot)>-1)
947 {
948 Lwpns.spr(Lwpns.idFirst(wHookshot))->y+=dy;
949 hs_starty+=(int32_t)dy;
950 }
951
952 if(Lwpns.idFirst(wHSHandle)>-1)
953 {
954 Lwpns.spr(Lwpns.idFirst(wHSHandle))->y+=dy;
955 }
956
957 if(chainlinks.Count()>0)
958 {
959 for(int32_t j=0; j<chainlinks.Count(); j++)
960 {
961 chainlinks.spr(j)->y+=dy;
962 }
963 }
964
965 y=new_y;
966
967 // A kludge
968 if(!diagonalMovement && dir>=left)
969 is_on_conveyor=true;
970 }
971
972 void HeroClass::setZfix(zfix new_z)
973 {
974 if(isSideViewHero())
975 return;
976
977 if(z==0 && new_z > 0)
978 {
979 switch(action)
980 {
981 case swimming:
982 {
983 diveclk=0;
984 action=walking; FFCore.setHeroAction(walking);
985 break;
986 }
987
988 case waterhold1:
989 {
990 action=landhold1; FFCore.setHeroAction(landhold1);
991 break;
992 }
993
994 case waterhold2:
995 {
996 action=landhold2; FFCore.setHeroAction(landhold2);
997 break;
998 }
999
1000 default:
1001 if(charging) //!DIMITODO: Let Hero jump while charging sword
1002 {
1003 reset_swordcharge();
1004 attackclk=0;
1005 }
1006
1007 break;
1008 }
1009 }
1010
1011 z=(new_z>0 ? new_z : zfix(0));
1012 }
1013
1014 void HeroClass::setFakeZfix(zfix new_z)
1015 {
1016 if(isSideViewHero())
1017 return;
1018
1019 if(fakez==0 && new_z > 0)
1020 {
1021 switch(action)
1022 {
1023 case swimming:
1024 {
1025 diveclk=0;
1026 action=walking; FFCore.setHeroAction(walking);
1027 break;
1028 }
1029
1030 case waterhold1:
1031 {
1032 action=landhold1; FFCore.setHeroAction(landhold1);
1033 break;
1034 }
1035
1036 case waterhold2:
1037 {
1038 action=landhold2; FFCore.setHeroAction(landhold2);
1039 break;
1040 }
1041
1042 default:
1043 if(charging) //!DIMITODO: Let Hero jump while charging sword
1044 {
1045 reset_swordcharge();
1046 attackclk=0;
1047 }
1048
1049 break;
1050 }
1051 }
1052
1053 fakez=(new_z>0 ? new_z : zfix(0));
1054 }
1055
1056 void HeroClass::setFall(zfix new_fall)
1057 {
1058 fall=new_fall;
1059 jumping=-1;
1060 }
1061 void HeroClass::setFakeFall(zfix new_fall)
1062 {
1063 fakefall=new_fall;
1064 jumping=-1;
1065 }
1066 void HeroClass::setClimbCoverX(int32_t new_x)
1067 {
1068 climb_cover_x=new_x;
1069 }
1070 void HeroClass::setClimbCoverY(int32_t new_y)
1071 {
1072 climb_cover_y=new_y;
1073 }
1074 int32_t HeroClass::getLStep()
1075 {
1076 return lstep;
1077 }
1078 int32_t HeroClass::getCharging()
1079 {
1080 return charging;
1081 }
1082 17 bool HeroClass::isCharged()
1083 {
1084 17 return spins>0;
1085 }
1086 int32_t HeroClass::getAttackClk()
1087 {
1088 return attackclk;
1089 }
1090 void HeroClass::setAttackClk(int32_t new_clk)
1091 {
1092 attackclk=new_clk;
1093 }
1094 void HeroClass::setCharging(int32_t new_charging)
1095 {
1096 charging=new_charging;
1097 }
1098 729839 int32_t HeroClass::getSwordClk()
1099 {
1100 729839 return swordclk;
1101 }
1102 732341 int32_t HeroClass::getItemClk()
1103 {
1104 732341 return itemclk;
1105 }
1106 void HeroClass::setSwordClk(int32_t newclk)
1107 {
1108 swordclk=newclk;
1109 verifyAWpn();
1110 }
1111 void HeroClass::setItemClk(int32_t newclk)
1112 {
1113 itemclk=newclk;
1114 }
1115 zfix HeroClass::getModifiedX()
1116 {
1117 zfix tempx=x;
1118
1119 if(screenscrolling&&(dir==left))
1120 {
1121 tempx=tempx+256;
1122 }
1123
1124 return tempx;
1125 }
1126
1127 zfix HeroClass::getModifiedY()
1128 {
1129 zfix tempy=y;
1130
1131 if(screenscrolling&&(dir==up))
1132 {
1133 tempy=tempy+176;
1134 }
1135
1136 return tempy;
1137 }
1138
1139 int32_t HeroClass::getDir()
1140 {
1141 return dir;
1142 }
1143 void HeroClass::setDir(int32_t newdir)
1144 {
1145 dir=newdir;
1146 reset_hookshot();
1147 }
1148 int32_t HeroClass::getHitDir()
1149 {
1150 return hitdir;
1151 }
1152 void HeroClass::setHitDir(int32_t newdir)
1153 {
1154 hitdir = newdir;
1155 }
1156 int32_t HeroClass::getClk()
1157 {
1158 return clk;
1159 }
1160 int32_t HeroClass::getPushing()
1161 {
1162 return pushing;
1163 }
1164 void HeroClass::Catch()
1165 {
1166 if(!inwallm && (action==none || action==walking))
1167 {
1168 SetAttack();
1169 attackclk=0;
1170 attack=wCatching;
1171 }
1172 }
1173
1174 1243 bool HeroClass::getClock()
1175 {
1176 1243 return superman;
1177 }
1178 void HeroClass::setClock(bool state)
1179 {
1180 superman=state;
1181 }
1182 15106 int32_t HeroClass::getAction() // Used by ZScript
1183 {
1184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15106 times.
15106 if(spins > 0)
1185 return isspinning;
1186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15106 times.
15106 else if(charging > 0)
1187 return ischarging;
1188
1/2
✓ Branch 0 taken 15106 times.
✗ Branch 1 not taken.
15106 else if(diveclk > 0)
1189 return isdiving;
1190 //else if (pushing > 0) return ispushing; //Needs a QR? -Z or make it an instruction as Hero->Pushing? Probably better, as that has a clk??
1191
1192 15106 return action;
1193 15106 }
1194
1195 1888 int32_t HeroClass::getAction2() // Used by ZScript new FFCore.actions
1196 {
1197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(spins > 0)
1198 return isspinning;
1199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 else if(charging > 0)
1200 return ischarging;
1201
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 else if(diveclk > 0)
1202 return isdiving;
1203 //else if (pushing > 0) return ispushing; //Needs a QR? -Z or make it an instruction as Hero->Pushing? Probably better, as that has a clk??
1204
1205 1888 return -1;
1206 1888 }
1207
1208 void HeroClass::setAction(actiontype new_action) // Used by ZScript
1209 {
1210 if(new_action==dying || new_action==won || new_action==scrolling ||
1211 new_action==inwind || new_action==ischarging || new_action==sideswimischarging ||
1212 new_action==hopping) //!DIMITODO: allow setting sideswimming stuff
1213 return; // Can't use these actions.
1214
1215 if (!isSideViewHero() && (new_action>=sideswimming && new_action <= sideswimischarging))
1216 return;
1217
1218 if(new_action==rafting)
1219 {
1220 if(get_bit(quest_rules, qr_DISALLOW_SETTING_RAFTING)) return;
1221 if(!(isRaftFlag(nextflag(x+8,y+8,dir,false))||isRaftFlag(nextflag(x+8,y+8,dir,true))))
1222 return;
1223 }
1224
1225
1226 if(magicitem>-1 && itemsbuf[magicitem].family==itype_faroreswind)
1227 {
1228 // Using Farore's Wind
1229 if(magiccastclk<96)
1230 {
1231 // Not cast yet; cancel it
1232 magicitem=-1;
1233 magiccastclk=0;
1234 }
1235 else
1236 // Already activated; don't do anything
1237 return;
1238 }
1239
1240 if(action==inwind) // Remove from whirlwind
1241 {
1242 xofs=0;
1243 whirlwind=0;
1244 lstep=0;
1245 if ( dontdraw < 2 ) { dontdraw=0; }
1246 }
1247 else if(action==freeze||action==sideswimfreeze) // Might be in enemy wind
1248 {
1249 sprite* wind=0;
1250 bool foundWind=false;
1251 for(int32_t i=0; i<Ewpns.Count(); i++)
1252 {
1253 wind=Ewpns.spr(i);
1254 if(wind->id==ewWind && wind->misc==999)
1255 {
1256 foundWind=true;
1257 break;
1258 }
1259 }
1260
1261 if(foundWind)
1262 {
1263 xofs=0;
1264 if ( dontdraw < 2 ) { dontdraw=false; }
1265 wind->misc=-1;
1266 x=wind->x;
1267 y=wind->y;
1268 }
1269 }
1270
1271 //Unless compat rule is on, reset hopping clocks when writing action!
1272 if(action == hopping && !get_bit(quest_rules,qr_NO_OVERWRITING_HOPPING))
1273 {
1274 hopclk = 0;
1275 hopdir = -1;
1276 }
1277
1278 if(new_action != attacking && new_action != sideswimattacking)
1279 {
1280 attackclk=0;
1281
1282 if(attack==wHookshot)
1283 reset_hookshot();
1284 }
1285 if(new_action != isspinning && new_action != sideswimisspinning)
1286 {
1287 charging = 0;
1288 spins = 0;
1289 }
1290
1291 if(action == falling && new_action != falling)
1292 {
1293 fallclk = 0; //Stop falling;
1294 }
1295
1296 if (action == rafting && new_action != rafting)
1297 {
1298 raftwarpx = x;//If you wanted to make Link stop rafting on a dock combo, don't make the dock retrigger the raft.
1299 raftwarpy = y;
1300 }
1301
1302 switch(new_action)
1303 {
1304 case isspinning:
1305 case sideswimisspinning:
1306 if(attack==wSword)
1307 {
1308 attackclk = SWORDCHARGEFRAME+1;
1309 charging = 0;
1310
1311 if(spins==0)
1312 spins = 5;
1313 }
1314 return;
1315
1316 case isdiving:
1317 if(action==swimming && diveclk==0)
1318 {
1319 int32_t flippers_id = current_item_id(itype_flippers);
1320 diveclk = (flippers_id < 0 ? 80 : (itemsbuf[flippers_id].misc1 + itemsbuf[flippers_id].misc2)); // Who cares about qr_NODIVING? It's the questmaker's business.
1321 }
1322 return;
1323
1324 case drowning:
1325 case sidedrowning:
1326 //I would add a sanity check to see if Hero is in water, but I *KNOW* that quests have used this
1327 // INTENTIONALLY while Hero is on Land, as a blink-out effect. :( -Z
1328 if(!drownclk)
1329 Drown();
1330
1331 break;
1332
1333 case lavadrowning:
1334 //Lavadrowning is just drowning but with a different argument. Simplicity! -Dimi
1335 if(!drownclk)
1336 Drown(1);
1337
1338 break;
1339
1340 case falling:
1341 if(!fallclk)
1342 {
1343 //If there is a pit under Hero, use it's combo.
1344 if(int32_t c = getpitfall(x+8,y+(bigHitbox?8:12))) fallCombo = c;
1345 else if(int32_t c = getpitfall(x,y+(bigHitbox?0:8))) fallCombo = c;
1346 else if(int32_t c = getpitfall(x+15,y+(bigHitbox?0:8))) fallCombo = c;
1347 else if(int32_t c = getpitfall(x,y+15)) fallCombo = c;
1348 else if(int32_t c = getpitfall(x+15,y+15)) fallCombo = c;
1349 //Else, use a null value; triggers default pit values
1350 else fallCombo = 0;
1351 fallclk = PITFALL_FALL_FRAMES;
1352 }
1353 break;
1354
1355 case gothit:
1356 case swimhit:
1357 case sideswimhit:
1358 if(!hclk)
1359 hclk=48;
1360
1361 break;
1362
1363 case landhold1:
1364 case landhold2:
1365 case waterhold1:
1366 case waterhold2:
1367 case sidewaterhold1:
1368 case sidewaterhold2:
1369 if(!holdclk)
1370 holdclk=130;
1371
1372 attack=none;
1373 break;
1374
1375 case attacking:
1376 case sideswimattacking:
1377 attack=none;
1378 break;
1379
1380 default:
1381 break;
1382 }
1383
1384 action=new_action; FFCore.setHeroAction(new_action);
1385 }
1386
1387 void HeroClass::setHeldItem(int32_t newitem)
1388 {
1389 holditem=newitem;
1390 }
1391 int32_t HeroClass::getHeldItem()
1392 {
1393 return holditem;
1394 }
1395 1888 bool HeroClass::isDiving()
1396 {
1397 1888 int32_t flippers_id = current_item_id(itype_flippers);
1398
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 return (diveclk > (flippers_id < 0 ? 30 : itemsbuf[flippers_id].misc2));
1399 }
1400 4626 bool HeroClass::isSwimming()
1401 {
1402
3/6
✓ Branch 0 taken 4626 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4626 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4626 times.
✗ Branch 5 not taken.
9252 return ((action==swimming)||(action==sideswimming)||IsSideSwim()||
1403
2/4
✓ Branch 0 taken 4626 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4626 times.
4626 (action==waterhold1)||(action==waterhold2)||
1404 4626 (hopclk==0xFF));
1405 }
1406
1407 15 void HeroClass::setDontDraw(byte new_dontdraw)
1408 {
1409 15 dontdraw=new_dontdraw;
1410 15 }
1411
1412 156 byte HeroClass::getDontDraw()
1413 {
1414 156 return dontdraw;
1415 }
1416
1417 void HeroClass::setHClk(int32_t newhclk)
1418 {
1419 hclk=newhclk;
1420 }
1421
1422 int32_t HeroClass::getHClk()
1423 {
1424 return hclk;
1425 }
1426
1427 int32_t HeroClass::getSpecialCave()
1428 {
1429 return specialcave; // used only by maps.cpp
1430 }
1431
1432 15 void HeroClass::init()
1433 {
1434 15 usecounts.clear();
1435 15 scale = 0;
1436 15 rotation = 0;
1437 15 do_animation = 1;
1438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if(lift_wpn)
1439 {
1440 delete lift_wpn;
1441 lift_wpn = nullptr;
1442 }
1443 15 liftclk = 0;
1444 15 tliftclk = 0;
1445 15 liftheight = 0;
1446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if ( dontdraw != 2 ) { dontdraw = 0; } //scripted dontdraw == 2, normal == 1, draw hero == 0
1447 15 hookshot_used=false;
1448 15 hookshot_frozen=false;
1449 15 onpassivedmg=false;
1450 15 dir = up;
1451 15 damageovertimeclk = 0;
1452 15 newconveyorclk = 0;
1453 15 switchhookclk = switchhookstyle = switchhookarg = switchhookmaxtime = 0;
1454
2/2
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 15 times.
120 for(auto q = 0; q < 7; ++q)
1455 105 hooked_undercombos[q] = -1;
1456 15 shiftdir = -1;
1457 15 sideswimdir = right;
1458 15 holddir = -1;
1459 15 landswim = 0;
1460 15 sdir = up;
1461 15 ilswim=true;
1462 15 walkable=false;
1463 15 moveflags = FLAG_OBEYS_GRAV | FLAG_CAN_PITFALL | FLAG_CAN_WATERDROWN;
1464 15 warp_sound = 0;
1465 15 subscr_speed = zinit.subscrSpeed;
1466 15 steprate = zinit.heroStep;
1467 15 is_warping = false;
1468 15 can_mirror_portal = true;
1469
1470 15 hammer_swim_up_offset = hammeroffsets[0];
1471 15 hammer_swim_down_offset = hammeroffsets[1];
1472 15 hammer_swim_left_offset = hammeroffsets[2];
1473 15 hammer_swim_right_offset = hammeroffsets[3];
1474
1475 15 prompt_combo = prompt_x = prompt_y = prompt_cset = 0;
1476
1477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if(get_bit(quest_rules,qr_NOARRIVALPOINT))
1478 {
1479 x=tmpscr->warpreturnx[0];
1480 y=tmpscr->warpreturny[0];
1481 }
1482 else
1483 {
1484 15 x=tmpscr->warparrivalx;
1485 15 y=tmpscr->warparrivaly;
1486 }
1487
1488 15 z=fakez=fall=fakefall=0;
1489 15 hzsz = 12; // So that flying peahats can still hit him.
1490
1491
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
15 if(x==0) dir=right;
1492
1493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if(x==240) dir=left;
1494
1495
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
15 if(y==0) dir=down;
1496
1497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if(y==160) dir=up;
1498
1499 15 lstep=0;
1500 15 skipstep=0;
1501 15 autostep=false;
1502 15 attackclk=holdclk=hoverclk=jumping=raftclk=0;
1503 15 attack=wNone;
1504 15 attackid=-1;
1505 15 action=none; FFCore.setHeroAction(none); tempaction=none;
1506 15 xofs=0;
1507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 yofs=(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset);
1508 15 cs=6;
1509 15 pushing=fairyclk=0;
1510 15 id=0;
1511 15 inlikelike=0;
1512 15 superman=inwallm=false;
1513 15 scriptcoldet=1;
1514 15 blowcnt=whirlwind=specialcave=0;
1515 15 hopclk=diveclk=fallclk=0;
1516 15 fallCombo = 0;
1517 15 pit_pulldir = -1;
1518 15 hopdir=-1;
1519 15 conveyor_flags=0;
1520 15 drunkclk=0;
1521 15 lstunclock = 0;
1522 15 is_conveyor_stunned=0;
1523 15 drawstyle=3;
1524 15 ffwarp = false;
1525 15 stepoutindex=stepoutwr=stepoutdmap=stepoutscr=0;
1526 15 stepnext=stepsecret=-1;
1527 15 ffpit = false;
1528 15 respawn_x=x;
1529 15 respawn_y=y;
1530 15 respawn_dmap=currdmap;
1531 15 respawn_scr=currscr;
1532 15 falling_oldy = y;
1533 15 magiccastclk=0;
1534 15 magicitem = nayruitem = -1;
1535 15 last_lens_id = 0; //Should be -1 (-Z)
1536 15 last_savepoint_id = 0;
1537 15 misc_internal_hero_flags = 0;
1538 15 last_cane_of_byrna_item_id = -1;
1539 15 on_sideview_ladder = false;
1540 15 switchblock_z = 0;
1541 15 switchblock_offset = false;
1542 15 extra_jump_count = 0;
1543 15 hoverflags = 0;
1544 15 lbunnyclock = 0;
1545
1546
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 15 times.
495 for(int32_t i=0; i<32; i++) miscellaneous[i] = 0;
1547
1548 15 setBigHitbox(get_bit(quest_rules, qr_LTTPCOLLISION));
1549 15 diagonalMovement=(get_bit(quest_rules,qr_LTTPWALK));
1550
1551 15 shield_active = false;
1552 15 shield_forcedir = -1;
1553 15 active_shield_id = -1;
1554
1555 //2.6
1556 15 preventsubscreenfalling = false; //-Z
1557 15 walkspeed = 0; //not used, yet. -Z
1558
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 15 times.
255 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) lastHitBy[q][0] = 0;
1559
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 15 times.
255 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) lastHitBy[q][1] = 0;
1560
2/2
✓ Branch 0 taken 2190 times.
✓ Branch 1 taken 15 times.
2205 for ( int32_t q = 0; q < wMax; q++ )
1561 {
1562 2190 defence[q] = hero_defence[q]; //we will need to have a Hero section in the quest load/save code! -Z Added 3/26/21 - Jman
1563 //zprint2("defence[%d] is: %d\n", q, defence[q]);
1564 2190 }
1565 //Run script!
1566
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
15 if (( FFCore.getQuestHeaderInfo(vZelda) >= 0x255 ) && (game->get_hasplayed()) ) //if (!hasplayed) runs in game_loop()
1567 {
1568 ZScriptVersion::RunScript(SCRIPT_PLAYER, SCRIPT_PLAYER_INIT, SCRIPT_PLAYER_INIT);
1569 FFCore.deallocateAllArrays(SCRIPT_PLAYER, SCRIPT_PLAYER_INIT);
1570 FFCore.initZScriptHeroScripts(); //Clear the stack and the refinfo data to be ready for Hero's active script.
1571 set_respawn_point(); //screen entry at spawn; //This should be after the init script, so that Hero->X and Hero->Y set by the script
1572 //are properly set by the engine.
1573 }
1574 15 FFCore.nostepforward = 0;
1575 15 }
1576
1577 2494 void HeroClass::draw_under(BITMAP* dest)
1578 {
1579 2494 int32_t c_raft=current_item_id(itype_raft);
1580 2494 int32_t c_ladder=current_item_id(itype_ladder);
1581
1582
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2494 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2494 if(action==rafting && c_raft >-1)
1583 {
1584 if(((dir==left) || (dir==right)) && (get_bit(quest_rules,qr_RLFIX)))
1585 {
1586 overtile16(dest, itemsbuf[c_raft].tile, x, y+playing_field_offset+4,
1587 itemsbuf[c_raft].csets&15, rotate_value((itemsbuf[c_raft].misc_flags>>2)&3)^3);
1588 }
1589 else
1590 {
1591 overtile16(dest, itemsbuf[c_raft].tile, x, y+playing_field_offset+4,
1592 itemsbuf[c_raft].csets&15, (itemsbuf[c_raft].misc_flags>>2)&3);
1593 }
1594 }
1595
1596
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2494 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2494 if(ladderx+laddery && c_ladder >-1)
1597 {
1598 if((ladderdir>=left) && (get_bit(quest_rules,qr_RLFIX)))
1599 {
1600 overtile16(dest, itemsbuf[c_ladder].tile, ladderx, laddery+playing_field_offset,
1601 itemsbuf[c_ladder].csets&15, rotate_value((itemsbuf[iRaft].misc_flags>>2)&3)^3);
1602 }
1603 else
1604 {
1605 overtile16(dest, itemsbuf[c_ladder].tile, ladderx, laddery+playing_field_offset,
1606 itemsbuf[c_ladder].csets&15, (itemsbuf[c_ladder].misc_flags>>2)&3);
1607 }
1608 }
1609 2494 }
1610
1611 void HeroClass::drawshadow(BITMAP* dest, bool translucent)
1612 {
1613 int32_t tempy=yofs;
1614 yofs+=8;
1615 shadowtile = wpnsbuf[spr_shadow].tile;
1616 sprite::drawshadow(dest,translucent);
1617 yofs=tempy;
1618 }
1619
1620 // The Stone of Agony reacts to these flags.
1621 bool HeroClass::agonyflag(int32_t flag)
1622 {
1623 switch(flag)
1624 {
1625 case mfWHISTLE:
1626 case mfBCANDLE:
1627 case mfARROW:
1628 case mfBOMB:
1629 case mfSBOMB:
1630 case mfBRANG:
1631 case mfMBRANG:
1632 case mfFBRANG:
1633 case mfSARROW:
1634 case mfGARROW:
1635 case mfRCANDLE:
1636 case mfWANDFIRE:
1637 case mfDINSFIRE:
1638 case mfWANDMAGIC:
1639 case mfREFMAGIC:
1640 case mfREFFIREBALL:
1641 case mfSWORD:
1642 case mfWSWORD:
1643 case mfMSWORD:
1644 case mfXSWORD:
1645 case mfSWORDBEAM:
1646 case mfWSWORDBEAM:
1647 case mfMSWORDBEAM:
1648 case mfXSWORDBEAM:
1649 case mfHOOKSHOT:
1650 case mfWAND:
1651 case mfHAMMER:
1652 case mfSTRIKE:
1653 return true;
1654 }
1655
1656 return false;
1657 }
1658
1659
1660 // Find the attack power of the current melee weapon.
1661 // The Whimsical Ring is applied on a target-by-target basis.
1662 171 int32_t HeroClass::weaponattackpower(int32_t itid)
1663 {
1664
1/2
✓ Branch 0 taken 171 times.
✗ Branch 1 not taken.
171 if(itid < 0)
1665 {
1666 itid = current_item_id(attack==wCByrna ? itype_cbyrna
1667 : attack==wWand ? itype_wand
1668 : attack==wHammer ? itype_hammer
1669 : itype_sword);
1670 }
1671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
171 int32_t power = attack==wCByrna ? itemsbuf[itid].misc4 : itemsbuf[itid].power;
1672
1673 // Multiply it by the power of the spin attack/quake hammer, if applicable.
1674
1/6
✓ Branch 0 taken 171 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
171 power *= (spins>0 ? itemsbuf[current_item_id(attack==wHammer ? itype_quakescroll : (spins>5 || current_item_id(itype_spinscroll) < 0) ? itype_spinscroll2 : itype_spinscroll)].power : 1);
1675 171 return power;
1676 }
1677
1678 #define NET_CLK_TOTAL 24
1679 #define NET_DIR_INC (NET_CLK_TOTAL/3)
1680 // Must only be called once per frame!
1681 void HeroClass::positionNet(weapon *w, int32_t itemid)
1682 {
1683 itemid = vbound(itemid, 0, MAXITEMS-1);
1684 int32_t t = w->o_tile,
1685 wx = 1, wy = 1;
1686
1687 //Invert positioning clock if right-handed animation
1688 int32_t clock = (itemsbuf[itemid].flags&ITEM_FLAG2 ? (NET_CLK_TOTAL-1)-attackclk : attackclk);
1689 if(clock >= NET_CLK_TOTAL)
1690 w->dead = 0;
1691 int32_t tiledir = dir;
1692 switch(dir)
1693 {
1694 case up:
1695 {
1696 if(clock < NET_DIR_INC) tiledir = l_up;
1697 else if(clock >= NET_DIR_INC*2) tiledir = r_up;
1698 break;
1699 }
1700 case down:
1701 {
1702 if(clock < NET_DIR_INC) tiledir = r_down;
1703 else if(clock >= NET_DIR_INC*2) tiledir = l_down;
1704 break;
1705 }
1706 case left:
1707 {
1708 if(clock < NET_DIR_INC) tiledir = l_down;
1709 else if(clock >= NET_DIR_INC*2) tiledir = l_up;
1710 break;
1711 }
1712 case right:
1713 {
1714 if(clock < NET_DIR_INC) tiledir = r_up;
1715 else if(clock >= NET_DIR_INC*2) tiledir = r_down;
1716 break;
1717 }
1718 }
1719 int32_t offs = 0;
1720 if(tiledir > right)
1721 offs = ((clock%NET_DIR_INC)<NET_DIR_INC/2) ? 1 : 0;
1722 else offs = vbound(((clock%NET_DIR_INC)/(NET_DIR_INC/3))-1,-1,1);
1723 //One of 8 positions
1724 switch(tiledir)
1725 {
1726 case up:
1727 {
1728 wx = 6*offs;
1729 wy = -14;
1730 break;
1731 }
1732 case r_up:
1733 {
1734 wx = (offs ? 10 : 14);
1735 wy = (offs ? -12 : -10);
1736 break;
1737 }
1738 case right:
1739 {
1740 wx = 14;
1741 wy = 6*offs;
1742 break;
1743 }
1744 case r_down:
1745 {
1746 wx = (offs ? 14 : 10);
1747 wy = (offs ? 10 : 12);
1748 break;
1749 }
1750 case down:
1751 {
1752 wx = -6*offs;
1753 wy = 14;
1754 break;
1755 }
1756 case l_down:
1757 {
1758 wx = (offs ? -10 : -14);
1759 wy = (offs ? 12 : 10);
1760 break;
1761 }
1762 case left:
1763 {
1764 wx = -14;
1765 wy = -6*offs;
1766 break;
1767 }
1768 case l_up:
1769 {
1770 wx = (offs ? -14 : -10);
1771 wy = (offs ? -10 : -12);
1772 break;
1773 }
1774 }
1775
1776 w->x = x+wx;
1777 w->y = y+wy-(54-(yofs))-fakez;
1778 w->z = (z+zofs);
1779 w->fakez = fakez;
1780 w->tile = t+tiledir;
1781 w->power = 0;
1782 w->dir = dir;
1783 w->doAutoRotate(true);
1784 }
1785 170 void HeroClass::positionSword(weapon *w, int32_t itemid)
1786 {
1787 //if ( w->ScriptGenerated ) return; //t/b/a for script-generated swords.
1788 //if ( itemsbuf[itemid].ScriptGenerated ) return; //t/b/a for script-generated swords.
1789 170 itemid=vbound(itemid, 0, MAXITEMS-1);
1790 // Place a sword weapon at the right spot.
1791 170 int32_t wy=1;
1792 170 int32_t wx=1;
1793 170 int32_t f=0,t,cs2;
1794
1795 170 t = w->o_tile;
1796 170 cs2 = w->o_cset;
1797 170 slashxofs=0;
1798 170 slashyofs=0;
1799
1800
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 67 times.
✓ Branch 4 taken 73 times.
170 switch(dir)
1801 {
1802 case up:
1803 20 wx=-1;
1804 20 wy=-12;
1805
1806
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
20 if(game->get_canslash() && w->id==wSword && itemsbuf[itemid].flags & ITEM_FLAG4 && charging==0)
1807 {
1808 if(attackclk>10) //extended stab
1809 {
1810 slashyofs-=3;
1811 wy-=2;
1812 }
1813
1814 if(attackclk>=14) //retracting stab
1815 {
1816 slashyofs+=3;
1817 wy+=2;
1818 }
1819 }
1820 else
1821 {
1822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if(attackclk==SWORDCHARGEFRAME)
1823 {
1824 wy+=4;
1825 }
1826
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 else if(attackclk==13)
1827 {
1828 2 wy+=4;
1829 2 }
1830
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 else if(attackclk==14)
1831 {
1832 2 wy+=8;
1833 2 }
1834 }
1835
1836 20 break;
1837
1838 case down:
1839 10 f=get_bit(quest_rules,qr_SWORDWANDFLIPFIX)?3:2;
1840 10 wy=11;
1841
1842
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10 if(game->get_canslash() && w->id==wSword && itemsbuf[itemid].flags & ITEM_FLAG4 && charging==0)
1843 {
1844 if(attackclk>10) //extended stab
1845 {
1846 slashyofs+=3;
1847 wy+=2;
1848 }
1849
1850 if(attackclk>=14) //retracting stab
1851 {
1852 slashyofs-=3;
1853 wy-=2;
1854 }
1855 }
1856 else
1857 {
1858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if(attackclk==SWORDCHARGEFRAME)
1859 {
1860 wy-=2;
1861 }
1862
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
10 else if(attackclk==13)
1863 {
1864 1 wy-=4;
1865 1 }
1866
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 else if(attackclk==14)
1867 {
1868 1 wy-=8;
1869 1 }
1870 }
1871
1872 10 break;
1873
1874 case left:
1875 67 f=1;
1876 67 wx=-11;
1877 67 ++t;
1878
1879
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
67 if(game->get_canslash() && w->id==wSword && itemsbuf[itemid].flags & ITEM_FLAG4 && charging==0)
1880 {
1881 if(attackclk>10) //extended stab
1882 {
1883 slashxofs-=4;
1884 wx-=7;
1885 }
1886
1887 if(attackclk>=14) //retracting stab
1888 {
1889 slashxofs+=3;
1890 wx+=7;
1891 }
1892 }
1893 else
1894 {
1895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 if(attackclk==SWORDCHARGEFRAME)
1896 {
1897 wx+=2;
1898 }
1899
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 60 times.
67 else if(attackclk==13)
1900 {
1901 7 wx+=4;
1902 7 }
1903
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 7 times.
60 else if(attackclk==14)
1904 {
1905 7 wx+=8;
1906 7 }
1907 }
1908
1909 67 break;
1910
1911 case right:
1912 73 wx=11;
1913 73 ++t;
1914
1915
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
73 if(game->get_canslash() && w->id==wSword && itemsbuf[itemid].flags & ITEM_FLAG4 && charging==0)
1916 {
1917 if(attackclk>10) //extended stab
1918 {
1919 slashxofs+=4;
1920 wx+=7;
1921 }
1922
1923 if(attackclk>=14) //retracting stab
1924 {
1925 slashxofs-=3;
1926 wx-=7;
1927 }
1928 }
1929 else
1930 {
1931
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if(attackclk==SWORDCHARGEFRAME)
1932 {
1933 wx-=2;
1934 }
1935
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 66 times.
73 else if(attackclk==13)
1936 {
1937 7 wx-=4;
1938 7 }
1939
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 7 times.
66 else if(attackclk==14)
1940 {
1941 7 wx-=8;
1942 7 }
1943 }
1944
1945 73 break;
1946 }
1947
1948
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
170 if(game->get_canslash() && itemsbuf[itemid].flags & ITEM_FLAG4 && attackclk<11)
1949 {
1950 int32_t wpn2=itemsbuf[itemid].wpn2;
1951 wpn2=vbound(wpn2, 0, MAXWPNS);
1952
1953 //slashing tiles
1954 switch(dir)
1955 {
1956 case up:
1957 wx=15;
1958 wy=-3;
1959 ++t;
1960 f=0; //starts pointing right
1961
1962 if(attackclk>=7)
1963 {
1964 wy-=9;
1965 wx-=3;
1966 t = wpnsbuf[wpn2].tile;
1967 cs2 = wpnsbuf[wpn2].csets&15;
1968 f=0;
1969 }
1970
1971 break;
1972
1973 case down:
1974 wx=-13;
1975 wy=-1;
1976 ++t;
1977 f=1; //starts pointing left
1978
1979 if(attackclk>=7)
1980 {
1981 wy+=15;
1982 wx+=2;
1983 t = wpnsbuf[wpn2].tile;
1984 cs2 = wpnsbuf[wpn2].csets&15;
1985 ++t;
1986 f=0;
1987 }
1988
1989 break;
1990
1991 case left:
1992 wx=3;
1993 wy=-15;
1994 --t;
1995 f=0; //starts pointing up
1996
1997 if(attackclk>=7)
1998 {
1999 wx-=15;
2000 wy+=3;
2001 slashxofs-=1;
2002 t = wpnsbuf[wpn2].tile;
2003 cs2 = wpnsbuf[wpn2].csets&15;
2004 t+=2;
2005 f=0;
2006 }
2007
2008 break;
2009
2010 case right:
2011 --t;
2012
2013 if(spins>0 || (itemsbuf[itemid].flags & ITEM_FLAG8))
2014 {
2015 wx=1;
2016 wy=13;
2017 f=2;
2018 }
2019 else
2020 {
2021 wx=3;
2022 wy=-15;
2023 f=0;
2024 }
2025
2026 if(attackclk>=7)
2027 {
2028 wx+=15;
2029 slashxofs+=1;
2030 t = wpnsbuf[wpn2].tile;
2031 cs2 = wpnsbuf[wpn2].csets&15;
2032
2033 if(spins>0 || (itemsbuf[itemid].flags & ITEM_FLAG8))
2034 {
2035 wx-=1;
2036 wy-=2;
2037 }
2038 else
2039 {
2040 t+=3;
2041 f=0;
2042 wy+=3;
2043 }
2044 }
2045
2046 break;
2047 }
2048 }
2049
2050 170 int32_t itemid2 = current_item_id(itype_chargering);
2051
2052
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
✓ Branch 2 taken 170 times.
✗ Branch 3 not taken.
170 if(charging>(itemid2>=0 ? itemsbuf[itemid2].misc1 : 64))
2053 {
2054 cs2=(BSZ ? (frame&3)+6 : ((frame>>2)&1)+7);
2055 }
2056
2057 /*if(BSZ || ((isdungeon() && currscr<128) && !get_bit(quest_rules,qr_HERODUNGEONPOSFIX)))
2058 {
2059 wy+=2;
2060 }*/
2061 170 w->x = x+wx;
2062 170 w->y = y+wy-(54-(yofs+slashyofs))-fakez;
2063 170 w->z = (z+zofs);
2064 170 w->tile = t;
2065 170 w->flip = f;
2066 170 w->power = weaponattackpower(itemid);
2067 170 w->dir = dir;
2068 170 w->doAutoRotate(true);
2069 170 }
2070
2071 2622 void HeroClass::draw(BITMAP* dest)
2072 {
2073 /*{
2074 char buf[36];
2075 //sprintf(buf,"%d %d %d %d %d %d %d",dir, action, attack, attackclk, charging, spins, tapping);
2076 textout_shadowed_ex(framebuf,font, buf, 2,72,WHITE,BLACK,-1);
2077 }*/
2078 int32_t oxofs, oyofs;
2079 2622 bool shieldModify = false;
2080
2/2
✓ Branch 0 taken 2302 times.
✓ Branch 1 taken 320 times.
2622 bool invisible=(dontdraw>0) || (tmpscr->flags3&fINVISHERO);
2081
2082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2622 times.
2622 if(action==dying)
2083 {
2084 if(!invisible)
2085 {
2086 if ( script_hero_cset > -1 ) cs = script_hero_cset;
2087 sprite::draw(dest);
2088 }
2089 return;
2090 }
2091
2092 2622 bool useltm=(get_bit(quest_rules,qr_EXPANDEDLTM) != 0);
2093
2094 2622 oxofs=xofs;
2095 2622 oyofs=yofs;
2096
2097
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 2302 times.
2622 if(!invisible)
2098
2/6
✓ Branch 0 taken 2302 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2302 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2302 yofs = oyofs-((!BSZ && isdungeon() && currscr<128 && !get_bit(quest_rules,qr_HERODUNGEONPOSFIX)) ? 2 : 0);
2099
2100 // Stone of Agony
2101 2622 bool agony=false;
2102 2622 int32_t agonyid = current_item_id(itype_agony);
2103
2104
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 2302 times.
2622 if(invisible)
2105 320 goto attack;
2106
2107
1/2
✓ Branch 0 taken 2302 times.
✗ Branch 1 not taken.
2302 if(agonyid>-1)
2108 {
2109 int32_t power=itemsbuf[agonyid].power;
2110 int32_t left=static_cast<int32_t>(x+8-power)&0xF0; // Check top-left pixel of each tile
2111 int32_t right=(static_cast<int32_t>(x+8+power)&0xF0)+16;
2112 int32_t top=static_cast<int32_t>(y+(bigHitbox ? 8 : 12)-power)&0xF0;
2113 int32_t bottom=(static_cast<int32_t>(y+(bigHitbox ? 8 : 12)+power)&0xF0)+16;
2114
2115 for(int32_t x=left; x<right; x+=16)
2116 {
2117 for(int32_t y=top; y<bottom; y+=16)
2118 {
2119 if(agonyflag(MAPFLAG(x, y)) || agonyflag(MAPCOMBOFLAG(x, y)))
2120 {
2121 agony=true;
2122 x=right; // Break out of outer loop
2123 break;
2124 }
2125 }
2126 }
2127 }
2128
2129 2302 cs = 6;
2130
1/2
✓ Branch 0 taken 2302 times.
✗ Branch 1 not taken.
2302 if ( script_hero_cset > -1 ) cs = script_hero_cset;
2131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2302 times.
4604 if(!get_bit(quest_rules,qr_HEROFLICKER))
2132 {
2133
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2302 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2302 if(superman && getCanFlicker())
2134 {
2135 cs += (((~frame)>>1)&3);
2136 }
2137
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2302 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2302 else if(hclk&&(NayrusLoveShieldClk<=0) && getCanFlicker())
2138 {
2139 cs += ((hclk>>1)&3);
2140 }
2141 2302 }
2142
2143 attack:
2144
2145
4/6
✓ Branch 0 taken 2384 times.
✓ Branch 1 taken 238 times.
✓ Branch 2 taken 2384 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2384 times.
2622 if(attackclk || (action==attacking||action==sideswimattacking))
2146 {
2147 /* Spaghetti code constants!
2148 * - Hero.attack contains a weapon type...
2149 * - which must be converted to an itype...
2150 * - which must be converted to an item ID...
2151 * - which is used to acquire a wpn ID! Aack!
2152 */
2153
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 238 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 238 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 238 times.
238 int32_t itype = (attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : attack==wBugNet ? itype_bugnet : itype_sword);
2154
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
238 int32_t itemid = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype);
2155 238 itemid=vbound(itemid, 0, MAXITEMS-1);
2156 // if ( itemsbuf[itemid].ScriptGenerated ) return; //t/b/a for script-generated swords.
2157
5/8
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 170 times.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 68 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 68 times.
238 if(attackclk>4||attack==wBugNet||(attack==wSword&&game->get_canslash()))
2158 {
2159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 if(attack == wBugNet)
2160 {
2161 weapon *w=NULL;
2162 bool found = false;
2163 for(int32_t q = 0; q < Lwpns.Count(); ++q)
2164 {
2165 w = (weapon*)Lwpns.spr(q);
2166 if(w->id == wBugNet)
2167 {
2168 found = true;
2169 break;
2170 }
2171 }
2172 if(!found)
2173 {
2174 Lwpns.add(new weapon((zfix)0,(zfix)0,(zfix)0,wBugNet,0,0,dir,itemid,getUID(),false,false,true));
2175
2176 w = (weapon*)Lwpns.spr(Lwpns.Count()-1);
2177 }
2178 positionNet(w, itemid);
2179 }
2180
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 170 times.
170 else if((attack==wSword || attack==wWand || ((attack==wFire || attack==wCByrna) && itemsbuf[itemid].wpn)) && wpnsbuf[itemsbuf[itemid].wpn].tile)
2181 {
2182 // Create a sword weapon at the right spot.
2183 170 weapon *w=NULL;
2184 170 bool found = false;
2185
2186 // Look for pre-existing sword
2187
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 209 times.
226 for(int32_t i=0; i<Lwpns.Count(); i++)
2188 {
2189 209 w = (weapon*)Lwpns.spr(i);
2190
2191
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 153 times.
209 if(w->id == (attack==wSword ? wSword : wWand))
2192 {
2193 153 found = true;
2194 153 break;
2195 }
2196 56 }
2197
2198
2/2
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 17 times.
170 if(!found) // Create one if sword nonexistant
2199 {
2200
5/10
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 17 times.
✗ Branch 9 not taken.
17 Lwpns.add(new weapon((zfix)0,(zfix)0,(zfix)0,(attack==wSword ? wSword : wWand),0,0,dir,itemid,getUID(),false,false,true));
2201 17 w = (weapon*)Lwpns.spr(Lwpns.Count()-1);
2202
2203 17 positionSword(w,itemid);
2204
2205 // Stone of Agony
2206
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if(agony)
2207 {
2208 w->y-=!(frame%zc_max(60-itemsbuf[agonyid].misc1,2))?1:0;
2209 }
2210 17 }
2211
2212 // These are set by positionSword(), above or in checkstab()
2213 170 yofs += slashyofs;
2214 170 xofs += slashxofs;
2215 170 slashyofs = slashxofs = 0;
2216 170 }
2217 170 }
2218
2219 238 if(attackclk<7
2220
3/4
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 102 times.
✓ Branch 2 taken 136 times.
✗ Branch 3 not taken.
238 || (attack==wSword && ((attackclk<(game->get_canslash()?15:13)
2221
4/6
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 102 times.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 34 times.
136 || FIXED_Z3_ANIMATION && attackclk<(game->get_canslash()?16:12))
2222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 || (charging>0 && attackclk!=SWORDCHARGEFRAME)))
2223
2/4
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
34 || ((attack==wWand || attack==wFire || attack==wCByrna) && attackclk<13)
2224
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34 times.
34 || (attack==wHammer && attackclk<=30)
2225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 || (attack==wBugNet && attackclk<NET_CLK_TOTAL))
2226 {
2227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 204 times.
204 if(!invisible)
2228 {
2229 204 herotile(&tile, &flip, &extend, (IsSideSwim())?ls_sideswimstab:ls_stab, dir, zinit.heroAnimationStyle);
2230
2/4
✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 204 times.
✗ Branch 3 not taken.
204 if (FIXED_Z3_ANIMATION)
2231 {
2232 if (attackclk >= 2) tile += (extend==2?2:1);
2233 if (attackclk >= 13) tile += (extend==2?2:1);
2234 }
2235
2236
1/18
✗ Branch 0 not taken.
✓ Branch 1 taken 204 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
204 if(((game->get_canslash() && (attack==wSword || attack==wWand || attack==wFire || attack==wCByrna)) && itemsbuf[itemid].flags&ITEM_FLAG4 && (attackclk<7||FIXED_Z3_ANIMATION&&(attackclk < 16))))
2237 {
2238 herotile(&tile, &flip, &extend, (IsSideSwim())?ls_sideswimslash:ls_slash, dir, zinit.heroAnimationStyle);
2239 if (FIXED_Z3_ANIMATION)
2240 {
2241 if (attackclk >= 7) tile += (extend==2?2:1);
2242 if (attackclk >= 11) tile += (extend==2?2:1);
2243 if (attackclk >= 14) tile += (extend==2?2:1);
2244 }
2245 }
2246
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 204 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
204 if (attack==wBugNet && !get_bit(quest_rules, qr_OLD_BUG_NET))
2247 {
2248 if ((dir == right && (itemsbuf[itemid].flags&ITEM_FLAG2)) || (dir != right && !(itemsbuf[itemid].flags&ITEM_FLAG2)))
2249 {
2250 if (attackclk < 9) herotile(&tile, &flip, &extend, ls_revslash, dir, zinit.heroAnimationStyle);
2251 if (attackclk > 15) herotile(&tile, &flip, &extend, (IsSideSwim())?ls_sideswimslash:ls_slash, dir, zinit.heroAnimationStyle);
2252 }
2253 else
2254 {
2255 if (attackclk < 9) herotile(&tile, &flip, &extend, (IsSideSwim())?ls_sideswimslash:ls_slash, dir, zinit.heroAnimationStyle);
2256 if (attackclk > 15) herotile(&tile, &flip, &extend, ls_revslash, dir, zinit.heroAnimationStyle);
2257 }
2258 }
2259
2260
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 204 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
204 if((attack==wHammer) && (attackclk<13))
2261 {
2262 herotile(&tile, &flip, &extend, (IsSideSwim())?ls_sideswimpound:ls_pound, dir, zinit.heroAnimationStyle);
2263 if (FIXED_Z3_ANIMATION)
2264 {
2265 if (attackclk >= 14) tile += (extend==2?2:1);
2266 if (attackclk >= 16) tile += (extend==2?2:1);
2267 }
2268 }
2269
2270
1/2
✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
204 if(useltm)
2271 {
2272 if ( script_hero_sprite <= 0 ) tile+=getTileModifier();
2273 }
2274
2275 // Stone of Agony
2276
1/2
✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
204 if(agony)
2277 {
2278 yofs-=!(frame%zc_max(60-itemsbuf[agonyid].misc1,3))?1:0;
2279 }
2280
2281 //Probably what makes Hero flicker, except for the QR check. What makes him flicker when that rule is off?! -Z
2282
2283 //I'm pretty sure he doesn't flicker when the rule is off. Also, take note of the parenthesis after the ! in this if statement; I was blind and didn't see it, and thought this code did something completely different. -Deedee
2284
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 204 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
204 if (!(get_bit(quest_rules, qr_HEROFLICKER) && ((superman || hclk) && (frame & 1))))
2285 {
2286 204 masked_draw(dest);
2287 204 }
2288
2289 //Prevent flickering -Z
2290
1/2
✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
204 if (!getCanFlicker()) masked_draw(dest);
2291 204 }
2292
2293
1/2
✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
204 if(attack!=wHammer)
2294 {
2295 204 xofs=oxofs;
2296 204 yofs=oyofs;
2297 204 return;
2298 }
2299 }
2300
2301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if(attack==wHammer) // To do: possibly abstract this out to a positionHammer routine?
2302 {
2303 int32_t wy=1;
2304 int32_t wx=1;
2305 int32_t f=0,t,cs2;
2306 weapon *w=NULL;
2307 bool found = false;
2308
2309 for(int32_t i=0; i<Lwpns.Count(); i++)
2310 {
2311 w = (weapon*)Lwpns.spr(i);
2312
2313 if(w->id == wHammer)
2314 {
2315 found = true;
2316 break;
2317 }
2318 }
2319
2320 if(!found)
2321 {
2322 Lwpns.add(new weapon((zfix)0,(zfix)0,(zfix)0,wHammer,0,0,dir,itemid,getUID(),false,false,true));
2323 w = (weapon*)Lwpns.spr(Lwpns.Count()-1);
2324 found = true;
2325 }
2326
2327 t = w->o_tile;
2328 cs2 = w->o_cset;
2329
2330 switch(dir)
2331 {
2332 case up:
2333 wx=-1;
2334 wy=-15;
2335 if (IsSideSwim())wy+=hammer_swim_up_offset;
2336
2337 if(attackclk>=13)
2338 {
2339 wx-=1;
2340 wy+=1;
2341 ++t;
2342 }
2343
2344 if(attackclk>=15)
2345 {
2346 if (IsSideSwim())wy-=hammer_swim_up_offset;
2347 ++t;
2348 }
2349
2350 break;
2351
2352 case down:
2353 wx=3;
2354 wy=-14;
2355 if (IsSideSwim())wy+=hammer_swim_down_offset;
2356 t+=3;
2357
2358 if(attackclk>=13)
2359 {
2360 wy+=16;
2361 ++t;
2362 }
2363
2364 if(attackclk>=15)
2365 {
2366 wx-=1;
2367 wy+=12;
2368 if (IsSideSwim())wy-=hammer_swim_down_offset;
2369 ++t;
2370 }
2371
2372 break;
2373
2374 case left:
2375 wx=0;
2376 wy=-14;
2377 if (IsSideSwim())wy+=hammer_swim_left_offset;
2378 t+=6;
2379 f=1;
2380
2381 if(attackclk>=13)
2382 {
2383 wx-=7;
2384 wy+=8;
2385 ++t;
2386 }
2387
2388 if(attackclk>=15)
2389 {
2390 wx-=8;
2391 wy+=8;
2392 if (IsSideSwim())wy-=hammer_swim_left_offset;
2393 ++t;
2394 }
2395
2396 break;
2397
2398 case right:
2399 wx=0;
2400 wy=-14;
2401 if (IsSideSwim())wy+=hammer_swim_right_offset;
2402 t+=6;
2403
2404 if(attackclk>=13)
2405 {
2406 wx+=7;
2407 wy+=8;
2408 ++t;
2409 }
2410
2411 if(attackclk>=15)
2412 {
2413 wx+=8;
2414 wy+=8;
2415 if (IsSideSwim())wy-=hammer_swim_right_offset;
2416 ++t;
2417 }
2418
2419 break;
2420 }
2421
2422 if(BSZ || ((isdungeon() && currscr<128) && !get_bit(quest_rules,qr_HERODUNGEONPOSFIX)))
2423 {
2424 wy+=2;
2425 }
2426
2427 // Stone of Agony
2428 if(agony)
2429 {
2430 wy-=!(frame%zc_max(60-itemsbuf[agonyid].misc1,3))?1:0;
2431 }
2432
2433 w->x = x+wx;
2434 w->y = y+wy-(54-yofs)-fakez;
2435 w->z = (z+zofs);
2436 w->tile = t;
2437 w->flip = f;
2438 w->hxsz=20;
2439 w->hysz=20;
2440
2441 if(dir>down)
2442 {
2443 w->hysz-=6;
2444 }
2445 else
2446 {
2447 w->hxsz-=6;
2448 w->hyofs=4;
2449 }
2450
2451 w->power = weaponattackpower(itemid);
2452
2453 if(attackclk==15 && z==0 && fakez==0 && (sideviewhammerpound() || !isSideViewHero()))
2454 {
2455 sfx(((iswaterex(MAPCOMBO(x+wx+8,y+wy), currmap, currscr, -1, x+wx+8, y+wy, true) || COMBOTYPE(x+wx+8,y+wy)==cSHALLOWWATER) && get_bit(quest_rules,qr_MORESOUNDS)) ? WAV_ZN1SPLASH : itemsbuf[itemid].usesound,pan(x.getInt()));
2456 }
2457
2458 xofs=oxofs;
2459 yofs=oyofs;
2460 return;
2461 }
2462 34 }
2463
2/4
✓ Branch 0 taken 2384 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2384 times.
2384 else if(!charging && !spins) // remove the sword
2464 {
2465
2/2
✓ Branch 0 taken 479 times.
✓ Branch 1 taken 2384 times.
2863 for(int32_t i=0; i<Lwpns.Count(); i++)
2466 {
2467 479 weapon *w = (weapon*)Lwpns.spr(i);
2468
2469
3/6
✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 479 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 479 times.
479 if(w->id == wSword || w->id == wHammer || w->id==wWand)
2470 w->dead=1;
2471 479 }
2472 2384 }
2473
2474
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 2098 times.
2418 if(invisible)
2475 {
2476 320 xofs=oxofs;
2477 320 yofs=oyofs;
2478 320 return;
2479 }
2480
2481
2/4
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2098 times.
2098 if(action != casting && action != sideswimcasting)
2482 {
2483 // Keep this consistent with checkspecial2, line 7800-ish...
2484
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2098 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2098 bool inwater = iswaterex(MAPCOMBO(x+4,y+9), currmap, currscr, -1, x+4, y+9, true, false) && iswaterex(MAPCOMBO(x+4,y+15), currmap, currscr, -1, x+4, y+15, true, false) && iswaterex(MAPCOMBO(x+11,y+9), currmap, currscr, -1, x+11, y+9, true, false) && iswaterex(MAPCOMBO(x+11,y+15), currmap, currscr, -1, x+11, y+15, true, false);
2485
2486 2098 int32_t jumping2 = int32_t(jumping*((zinit.gravity2 / 100)/16.0));
2487 2098 bool noliftspr = get_bit(quest_rules,qr_NO_LIFT_SPRITE);
2488 //if (jumping!=0) al_trace("%d %d %f %d\n",jumping,zinit.gravity,zinit.gravity/16.0,jumping2);
2489
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2098 times.
✗ Branch 3 not taken.
2098 switch(zinit.heroAnimationStyle)
2490 {
2491 case las_original: //normal
2492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2098 times.
2098 if(action==drowning)
2493 {
2494 if(inwater)
2495 {
2496 herotile(&tile, &flip, &extend, (drownclk > 60) ? ls_float : ls_drown, dir, zinit.heroAnimationStyle);
2497 if ( script_hero_sprite <= 0 ) tile+=((frame>>3) & 1)*(extend==2?2:1);
2498 }
2499 else
2500 {
2501 xofs=oxofs;
2502 yofs=oyofs;
2503 return;
2504 }
2505 }
2506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2098 times.
2098 else if(action==lavadrowning)
2507 {
2508 herotile(&tile, &flip, &extend, (drownclk > 60) ? ls_float : ls_lavadrown, dir, zinit.heroAnimationStyle);
2509 if ( script_hero_sprite <= 0 ) tile+=((frame>>3) & 1)*(extend==2?2:1);
2510 }
2511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2098 times.
2098 else if(action==sidedrowning)
2512 {
2513 herotile(&tile, &flip, &extend, ls_sidedrown, down, zinit.heroAnimationStyle);
2514 if ( script_hero_sprite <= 0 ) tile+=((frame>>3) & 1)*(extend==2?2:1);
2515 }
2516
2/4
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2098 times.
2098 else if (action == sideswimming || action == sideswimhit)
2517 {
2518 herotile(&tile, &flip, &extend, ls_sideswim, dir, zinit.heroAnimationStyle);
2519
2520 if(lstep>=6)
2521 {
2522 if(dir==up)
2523 {
2524 if ( script_hero_sprite <= 0 ) ++flip;
2525 }
2526 else
2527 {
2528 if ( script_hero_sprite <= 0 ) extend==2?tile+=2:++tile;
2529 }
2530 }
2531 }
2532
3/6
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2098 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2098 times.
2098 else if(action==swimming || action==swimhit || hopclk==0xFF)
2533 {
2534 herotile(&tile, &flip, &extend, is_moving()?ls_swim:ls_float, dir, zinit.heroAnimationStyle);
2535
2536 if(lstep>=6)
2537 {
2538 if(dir==up)
2539 {
2540 if ( script_hero_sprite <= 0 ) ++flip;
2541 }
2542 else
2543 {
2544 if ( script_hero_sprite <= 0 ) extend==2?tile+=2:++tile;
2545 }
2546 }
2547
2548 if(isDiving())
2549 {
2550 herotile(&tile, &flip, &extend, ls_dive, dir, zinit.heroAnimationStyle);
2551 if ( script_hero_sprite <= 0 ) tile+=((frame>>3) & 1)*(extend==2?2:1);
2552 }
2553 }
2554
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2098 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2098 else if(charging > 0 && attack != wHammer)
2555 {
2556 herotile(&tile, &flip, &extend, (IsSideSwim())?ls_sideswimcharge:ls_charge, dir, zinit.heroAnimationStyle);
2557
2558 if(lstep>=6)
2559 {
2560 if(dir==up)
2561 {
2562 if ( script_hero_sprite <= 0 ) ++flip;
2563 }
2564 else
2565 {
2566 if ( script_hero_sprite <= 0 ) extend==2?tile+=2:++tile;
2567 }
2568 }
2569 }
2570
3/12
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2098 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2098 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2098 else if((z>0 || fakez>0 || isSideViewHero()) && jumping2>0 && jumping2<24 && game->get_life()>0 && action!=rafting)
2571 {
2572 herotile(&tile, &flip, &extend, ls_jump, dir, zinit.heroAnimationStyle);
2573 if ( script_hero_sprite <= 0 ) tile+=((int32_t)jumping2/8)*(extend==2?2:1);
2574 }
2575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2098 times.
2098 else if(fallclk>0)
2576 {
2577 herotile(&tile, &flip, &extend, ls_falling, dir, zinit.heroAnimationStyle);
2578 if ( script_hero_sprite <= 0 ) tile+=((PITFALL_FALL_FRAMES-fallclk)/10)*(extend==2?2:1);
2579 }
2580
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2098 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2098 else if(!noliftspr&&action==lifting&&isLifting())
2581 {
2582 herotile(&tile, &flip, &extend, ls_lifting, dir, zinit.heroAnimationStyle);
2583 if(script_hero_sprite <= 0)
2584 {
2585 auto frames = vbound(liftingspr[dir][spr_frames],1,255);
2586 auto speed = tliftclk/frames;
2587 if (speed < 1) speed = 1;
2588 auto curframe = (tliftclk - liftclk) / speed;
2589 if (!tliftclk) curframe = frames - 1;
2590 if(unsigned(curframe) < frames)
2591 tile += curframe * (extend == 2 ? 2 : 1);
2592 }
2593 }
2594 else
2595 {
2596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2098 times.
2098 if(IsSideSwim())
2597 herotile(&tile, &flip, &extend, ls_sideswim, dir, zinit.heroAnimationStyle);
2598
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2098 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2098 else if(!noliftspr&&isLifting())
2599 herotile(&tile, &flip, &extend, ls_liftwalk, dir, zinit.heroAnimationStyle);
2600 2098 else herotile(&tile, &flip, &extend, ls_walk, dir, zinit.heroAnimationStyle);
2601
2602
2/2
✓ Branch 0 taken 1373 times.
✓ Branch 1 taken 725 times.
2098 if(dir>up)
2603 {
2604 1373 useltm=true;
2605 1373 shieldModify=true;
2606 1373 }
2607
2608
2/2
✓ Branch 0 taken 1089 times.
✓ Branch 1 taken 1009 times.
2098 if(lstep>=6)
2609 {
2610
2/2
✓ Branch 0 taken 248 times.
✓ Branch 1 taken 761 times.
1009 if(dir==up)
2611 {
2612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248 times.
248 if ( script_hero_sprite <= 0 ) ++flip;
2613 248 }
2614 else
2615 {
2616
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 761 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 761 times.
761 if ( script_hero_sprite <= 0 ) extend==2?tile+=2:++tile;
2617 }
2618 1009 }
2619 }
2620
2621 2098 break;
2622
2623 case las_bszelda: //BS
2624 if(action==drowning)
2625 {
2626 if(inwater)
2627 {
2628 herotile(&tile, &flip, &extend, (drownclk > 60) ? ls_float : ls_drown, dir, zinit.heroAnimationStyle);
2629 if ( script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2630 }
2631 else
2632 {
2633 xofs=oxofs;
2634 yofs=oyofs;
2635 return;
2636 }
2637 }
2638 else if (action == sidedrowning)
2639 {
2640 herotile(&tile, &flip, &extend, ls_sidedrown, down, zinit.heroAnimationStyle);
2641 if ( script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2642 }
2643 else if(action==lavadrowning)
2644 {
2645 herotile(&tile, &flip, &extend, (drownclk > 60) ? ls_float : ls_lavadrown, dir, zinit.heroAnimationStyle);
2646 if ( script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2647 }
2648 else if (action == sideswimming || action == sideswimhit)
2649 {
2650 herotile(&tile, &flip, &extend, ls_sideswim, dir, zinit.heroAnimationStyle);
2651
2652 if ( script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2653 }
2654 else if(action==swimming || action==swimhit || hopclk==0xFF)
2655 {
2656 if (get_bit(quest_rules, qr_COPIED_SWIM_SPRITES))
2657 {
2658 herotile(&tile, &flip, &extend, ls_walk, dir, zinit.heroAnimationStyle);
2659 }
2660 else
2661 {
2662 herotile(&tile, &flip, &extend, is_moving()?ls_swim:ls_float, dir, zinit.heroAnimationStyle);
2663 }
2664 if ( script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2665
2666 if(isDiving())
2667 {
2668 if (get_bit(quest_rules, qr_COPIED_SWIM_SPRITES))
2669 {
2670 herotile(&tile, &flip, &extend, ls_walk, dir, zinit.heroAnimationStyle);
2671 }
2672 else
2673 {
2674 herotile(&tile, &flip, &extend, ls_dive, dir, zinit.heroAnimationStyle);
2675 }
2676 if ( script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2677 }
2678 }
2679 else if(charging > 0 && attack != wHammer)
2680 {
2681 herotile(&tile, &flip, &extend, (IsSideSwim())?ls_sideswimcharge:ls_charge, dir, zinit.heroAnimationStyle);
2682 if ( script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2683 }
2684 else if((z>0 || fakez>0 || isSideViewHero()) && jumping2>0 && jumping2<24 && game->get_life()>0)
2685 {
2686 herotile(&tile, &flip, &extend, ls_jump, dir, zinit.heroAnimationStyle);
2687 if ( script_hero_sprite <= 0 ) tile+=((int32_t)jumping2/8)*(extend==2?2:1);
2688 }
2689 else if(fallclk>0)
2690 {
2691 herotile(&tile, &flip, &extend, ls_falling, dir, zinit.heroAnimationStyle);
2692 if ( script_hero_sprite <= 0 ) tile += ((PITFALL_FALL_FRAMES-fallclk)/10)*(extend==2?2:1);
2693 }
2694 else if(!noliftspr&&action==lifting&&isLifting())
2695 {
2696 herotile(&tile, &flip, &extend, ls_lifting, dir, zinit.heroAnimationStyle);
2697 if(script_hero_sprite <= 0)
2698 {
2699 auto frames = vbound(liftingspr[dir][spr_frames],1,255);
2700 auto speed = tliftclk/frames;
2701 if (speed < 1) speed = 1;
2702 auto curframe = (tliftclk - liftclk) / speed;
2703 if (!tliftclk) curframe = frames - 1;
2704 if(unsigned(curframe) < frames)
2705 tile += curframe * (extend == 2 ? 2 : 1);
2706 }
2707 }
2708 else
2709 {
2710 if(IsSideSwim())
2711 herotile(&tile, &flip, &extend, ls_sideswim, dir, zinit.heroAnimationStyle);
2712 else if(!noliftspr&&isLifting())
2713 herotile(&tile, &flip, &extend, ls_liftwalk, dir, zinit.heroAnimationStyle);
2714 else herotile(&tile, &flip, &extend, ls_walk, dir, zinit.heroAnimationStyle);
2715
2716 if(dir>up)
2717 {
2718 useltm=true;
2719 shieldModify=true;
2720 }
2721
2722 /*
2723 else if (dir==up)
2724 {
2725 useltm=true;
2726 }
2727 */
2728 if (script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2729 }
2730
2731 break;
2732
2733 case las_zelda3slow: //8-frame Zelda 3 (slow)
2734 case las_zelda3: //8-frame Zelda 3
2735 if(action == drowning)
2736 {
2737 if(inwater)
2738 {
2739 herotile(&tile, &flip, &extend, (drownclk > 60) ? ls_float : ls_drown, dir, zinit.heroAnimationStyle);
2740 if (script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2741 }
2742 else
2743 {
2744 xofs=oxofs;
2745 yofs=oyofs;
2746 return;
2747 }
2748 }
2749 else if(action == lavadrowning)
2750 {
2751 herotile(&tile, &flip, &extend, (drownclk > 60) ? ls_float : ls_lavadrown, dir, zinit.heroAnimationStyle);
2752 if (script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2753
2754 }
2755 else if(action == sidedrowning)
2756 {
2757 herotile(&tile, &flip, &extend, ls_sidedrown, down, zinit.heroAnimationStyle);
2758 if (script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2759 }
2760 else if (action == sideswimming || action == sideswimhit)
2761 {
2762 herotile(&tile, &flip, &extend, ls_sideswim, dir, zinit.heroAnimationStyle);
2763
2764 if (script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2765 }
2766 else if(action == swimming || action==swimhit || hopclk==0xFF)
2767 {
2768 herotile(&tile, &flip, &extend, is_moving()?ls_swim:ls_float, dir, zinit.heroAnimationStyle);
2769 if (script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2770
2771 if(isDiving())
2772 {
2773 herotile(&tile, &flip, &extend, ls_dive, dir, zinit.heroAnimationStyle);
2774 if (script_hero_sprite <= 0 ) tile += anim_3_4(lstep,7)*(extend==2?2:1);
2775 }
2776 }
2777 else if(charging > 0 && attack != wHammer)
2778 {
2779 herotile(&tile, &flip, &extend, (IsSideSwim())?ls_sideswimcharge:ls_charge, dir, zinit.heroAnimationStyle);
2780 if (script_hero_sprite <= 0 ) tile+=(extend==2?2:1);
2781 //int32_t l=hero_count/hero_animation_speed;
2782 int32_t l=(hero_count/hero_animation_speed)&15;
2783 //int32_t l=((p[lt_clock]/hero_animation_speed)&15);
2784 l-=((l>3)?1:0)+((l>12)?1:0);
2785 if (script_hero_sprite <= 0 ) tile+=(l/2)*(extend==2?2:1);
2786 }
2787 else if((z>0 || fakez>0 || isSideViewHero()) && jumping2>0 && jumping2<24 && game->get_life()>0)
2788 {
2789 herotile(&tile, &flip, &extend, ls_jump, dir, zinit.heroAnimationStyle);
2790 if (script_hero_sprite <= 0 ) tile+=((int32_t)jumping2/8)*(extend==2?2:1);
2791 }
2792 else if(fallclk>0)
2793 {
2794 herotile(&tile, &flip, &extend, ls_falling, dir, zinit.heroAnimationStyle);
2795 if (script_hero_sprite <= 0 ) tile += ((PITFALL_FALL_FRAMES-fallclk)/10)*(extend==2?2:1);
2796 }
2797 else if(!noliftspr&&action==lifting&&isLifting())
2798 {
2799 herotile(&tile, &flip, &extend, ls_lifting, dir, zinit.heroAnimationStyle);
2800 if(script_hero_sprite <= 0)
2801 {
2802 auto frames = vbound(liftingspr[dir][spr_frames],1,255);
2803 auto speed = tliftclk/frames;
2804 if (speed < 1) speed = 1;
2805 auto curframe = (tliftclk-liftclk)/speed;
2806 if (!tliftclk) curframe = frames - 1;
2807 if(unsigned(curframe) < frames)
2808 tile += curframe * (extend == 2 ? 2 : 1);
2809 }
2810 }
2811 else
2812 {
2813 if(IsSideSwim())
2814 herotile(&tile, &flip, &extend, ls_sideswim, dir, zinit.heroAnimationStyle);
2815 else if(!noliftspr&&isLifting())
2816 herotile(&tile, &flip, &extend, ls_liftwalk, dir, zinit.heroAnimationStyle);
2817 else herotile(&tile, &flip, &extend, ls_walk, dir, zinit.heroAnimationStyle);
2818
2819 if(action == walking || action == climbcoverbottom || action == climbcovertop)
2820 {
2821 if (script_hero_sprite <= 0 ) tile += (extend == 2 ? 2 : 1);
2822 }
2823
2824 if(dir>up)
2825 {
2826 useltm=true;
2827 shieldModify=true;
2828 }
2829
2830 if(action == walking || action == hopping || action == climbcoverbottom || action == climbcovertop)
2831 {
2832 //tile+=(extend==2?2:1);
2833 //tile+=(((active_count>>2)%8)*(extend==2?2:1));
2834 int32_t l = hero_count / hero_animation_speed;
2835 l -= ((l > 3) ? 1 : 0) + ((l > 12) ? 1 : 0);
2836 if (script_hero_sprite <= 0 ) tile += (l / 2) * (extend == 2 ? 2 : 1);
2837 }
2838 }
2839
2840 break;
2841
2842 default:
2843 break;
2844 }
2845 2098 }
2846
2847
2/6
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2098 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2098 yofs = oyofs-((!BSZ && isdungeon() && currscr<128 && !get_bit(quest_rules,qr_HERODUNGEONPOSFIX)) ? 2 : 0);
2848
2849
1/2
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
2098 if(action==won)
2850 {
2851 yofs=(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) - 2;
2852 }
2853
2854
3/4
✓ Branch 0 taken 1968 times.
✓ Branch 1 taken 130 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1968 times.
2098 if(action==landhold1 || action==landhold2)
2855 {
2856 130 useltm=(get_bit(quest_rules,qr_EXPANDEDLTM) != 0);
2857
2/6
✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 130 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
130 yofs = oyofs-((!BSZ && isdungeon() && currscr<128 && !get_bit(quest_rules,qr_HERODUNGEONPOSFIX)) ? 2 : 0);
2858 130 herotile(&tile, &flip, &extend, (action==landhold1)?ls_landhold1:ls_landhold2, dir, zinit.heroAnimationStyle);
2859 130 }
2860
2/4
✓ Branch 0 taken 1968 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1968 times.
1968 else if(action==waterhold1 || action==waterhold2)
2861 {
2862 useltm=(get_bit(quest_rules,qr_EXPANDEDLTM) != 0);
2863 herotile(&tile, &flip, &extend, (action==waterhold1)?ls_waterhold1:ls_waterhold2, dir, zinit.heroAnimationStyle);
2864 }
2865
2/4
✓ Branch 0 taken 1968 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1968 times.
1968 else if(action==sidewaterhold1 || action==sidewaterhold2)
2866 {
2867 useltm=(get_bit(quest_rules,qr_EXPANDEDLTM) != 0);
2868 herotile(&tile, &flip, &extend, (action==sidewaterhold1)?ls_sidewaterhold1:ls_sidewaterhold2, dir, zinit.heroAnimationStyle);
2869 }
2870
2871
2/4
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2098 times.
2098 if(action!=casting && action!=sideswimcasting)
2872 {
2873
2/2
✓ Branch 0 taken 855 times.
✓ Branch 1 taken 1243 times.
2098 if(useltm)
2874 {
2875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1243 times.
1243 if (script_hero_sprite <= 0 ) tile+=getTileModifier();
2876 1243 }
2877 2098 }
2878
2879 // Stone of Agony
2880
1/2
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
2098 if(agony)
2881 {
2882 yofs-=!(frame%zc_max(60-itemsbuf[agonyid].misc1,3))?1:0;
2883 }
2884
2885
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2098 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2098 if(!(get_bit(quest_rules,qr_HEROFLICKER)&&((superman||hclk)&&(frame&1))))
2886 {
2887 2098 masked_draw(dest);
2888 2098 }
2889
2890 //draw held items after Hero so they don't go behind his head
2891
3/4
✓ Branch 0 taken 1968 times.
✓ Branch 1 taken 130 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1968 times.
2098 if(action==landhold1 || action==landhold2)
2892 {
2893
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 130 times.
130 if(holditem > -1)
2894 {
2895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 130 times.
130 if(get_bit(quest_rules,qr_HOLDITEMANIMATION))
2896 {
2897 putitem2(dest,x-((action==landhold1)?4:0),y+yofs-16-(get_bit(quest_rules, qr_NOITEMOFFSET))-fakez-z,holditem,lens_hint_item[holditem][0], lens_hint_item[holditem][1], 0);
2898 }
2899 else
2900 {
2901 130 putitem(dest,x-((action==landhold1)?4:0),y+yofs-16-(get_bit(quest_rules, qr_NOITEMOFFSET))-fakez-z,holditem);
2902 }
2903 130 }
2904 130 }
2905
2/4
✓ Branch 0 taken 1968 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1968 times.
1968 else if(action==waterhold1 || action==waterhold2)
2906 {
2907 if(holditem > -1)
2908 {
2909 if(get_bit(quest_rules,qr_HOLDITEMANIMATION))
2910 {
2911 putitem2(dest,x-((action==waterhold1)?4:0),y+yofs-12-(get_bit(quest_rules, qr_NOITEMOFFSET))-fakez-z,holditem,lens_hint_item[holditem][0], lens_hint_item[holditem][1], 0);
2912 }
2913 else
2914 {
2915 putitem(dest,x-((action==waterhold1)?4:0),y+yofs-12-(get_bit(quest_rules, qr_NOITEMOFFSET))-fakez-z,holditem);
2916 }
2917 }
2918 }
2919
2/4
✓ Branch 0 taken 1968 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1968 times.
1968 else if(action==sidewaterhold1 || action==sidewaterhold2) //!DIMITODO: Check to see if this looks right or if it needs waterhold's offset.
2920 {
2921 if(holditem > -1)
2922 {
2923 if(get_bit(quest_rules,qr_HOLDITEMANIMATION))
2924 {
2925 putitem2(dest,x-((action==sidewaterhold1)?4:0),y+yofs-16-(get_bit(quest_rules, qr_NOITEMOFFSET))-fakez-z,holditem,lens_hint_item[holditem][0], lens_hint_item[holditem][1], 0);
2926 }
2927 else
2928 {
2929 putitem(dest,x-((action==sidewaterhold1)?4:0),y+yofs-16-(get_bit(quest_rules, qr_NOITEMOFFSET))-fakez-z,holditem);
2930 }
2931 }
2932 }
2933
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2098 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2098 if(fairyclk==0||(get_bit(quest_rules,qr_NOHEARTRING)))
2934 {
2935 2098 xofs=oxofs;
2936 2098 yofs=oyofs;
2937 2098 return;
2938 }
2939
2940 double a2 = fairyclk*int64_t(2)*PI/80 + (PI/2);
2941 int32_t hearts=0;
2942 // int32_t htile = QHeader.dat_flags[ZQ_TILES] ? 2 : 0;
2943 int32_t htile = 2;
2944
2945 do
2946 {
2947 int32_t nx=125;
2948
2949 if(get_bit(quest_rules,qr_HEARTRINGFIX))
2950 {
2951 nx=x;
2952 }
2953
2954 int32_t ny=88;
2955
2956 if(get_bit(quest_rules,qr_HEARTRINGFIX))
2957 {
2958 ny=y;
2959 }
2960
2961 double tx = zc::math::Cos(a2)*53 +nx;
2962 double ty = -zc::math::Sin(a2)*53 +ny+playing_field_offset;
2963 overtile8(dest,htile,int32_t(tx),int32_t(ty),1,0);
2964 a2-=PI/4;
2965 ++hearts;
2966 }
2967 while(a2>PI/2 && hearts<8);
2968
2969 xofs=oxofs;
2970 yofs=oyofs;
2971 2622 }
2972
2973 2302 void HeroClass::masked_draw(BITMAP* dest)
2974 {
2975
1/12
✗ Branch 0 not taken.
✓ Branch 1 taken 2302 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2302 if(isdungeon() && currscr<128 && (x<16 || x>224 || y<18 || y>146) && !get_bit(quest_rules,qr_FREEFORM))
2976 {
2977 // clip under doorways
2978 BITMAP *sub=create_sub_bitmap(dest,16,playing_field_offset+16,224,144);
2979
2980 if(sub!=NULL)
2981 {
2982 yofs -= (playing_field_offset+16);
2983 xofs -= 16;
2984 sprite::draw(sub);
2985 if(lift_wpn)
2986 {
2987 handle_lift(false);
2988 bool shad = lift_wpn->has_shadow;
2989 lift_wpn->has_shadow = false;
2990 lift_wpn->draw(sub);
2991 lift_wpn->has_shadow = shad;
2992 }
2993 prompt_draw(sub);
2994 xofs+=16;
2995 yofs += (playing_field_offset+16);
2996 destroy_bitmap(sub);
2997 }
2998 }
2999 else
3000 {
3001 2302 sprite::draw(dest);
3002
1/2
✓ Branch 0 taken 2302 times.
✗ Branch 1 not taken.
2302 if(lift_wpn)
3003 {
3004 handle_lift(false);
3005 bool shad = lift_wpn->has_shadow;
3006 lift_wpn->has_shadow = false;
3007 lift_wpn->draw(dest);
3008 lift_wpn->has_shadow = shad;
3009 }
3010 2302 prompt_draw(dest);
3011 }
3012
3013 2302 return;
3014 }
3015 2302 void HeroClass::prompt_draw(BITMAP* dest)
3016 {
3017
1/2
✓ Branch 0 taken 2302 times.
✗ Branch 1 not taken.
2302 if(!prompt_combo) return;
3018 int32_t sx = real_x(x+xofs+prompt_x);
3019 int32_t sy = real_y(y + yofs + prompt_y) - real_z(z + zofs);
3020 sy -= fake_z(fakez);
3021 overcombo(dest, sx, sy, prompt_combo, prompt_cset);
3022 return;
3023 2302 }
3024
3025 2 void collectitem_script(int32_t id)
3026 {
3027
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(itemsbuf[id].collect_script)
3028 {
3029 //clear item script stack.
3030 //ri = &(itemScriptData[id]);
3031 //ri->Clear();
3032 //itemCollectScriptData[id].Clear();
3033 //for ( int32_t q = 0; q < 1024; q++ ) item_collect_stack[id][q] = 0;
3034 ri = &(itemCollectScriptData[id]);
3035 for ( int32_t q = 0; q < 1024; q++ ) item_collect_stack[id][q] = 0xFFFF;
3036 ri->Clear();
3037 //ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[id].collect_script, ((id & 0xFFF)*-1));
3038
3039 if ( id > 0 && !(item_collect_doscript[id] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) ) //No collect script on item 0.
3040 {
3041 item_collect_doscript[id] = 1;
3042 itemscriptInitialised[id] = 0;
3043 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[id].collect_script, ((id)*-1));
3044 //if ( !get_bit(quest_rules, qr_ITEMSCRIPTSKEEPRUNNING) )
3045 FFCore.deallocateAllArrays(SCRIPT_ITEM,-(id));
3046 }
3047 else if (id == 0 && !(item_collect_doscript[id] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING))) //item 0
3048 {
3049 item_collect_doscript[id] = 1;
3050 itemscriptInitialised[id] = 0;
3051 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[id].collect_script, COLLECT_SCRIPT_ITEM_ZERO);
3052 //if ( !get_bit(quest_rules, qr_ITEMSCRIPTSKEEPRUNNING) )
3053 FFCore.deallocateAllArrays(SCRIPT_ITEM,COLLECT_SCRIPT_ITEM_ZERO);
3054 }
3055 //runningItemScripts[id] = 0;
3056 }
3057 2 }
3058 18 void passiveitem_script(int32_t id, bool doRun = false)
3059 {
3060 //Passive item scripts on colelction
3061
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
18 if(itemsbuf[id].script && ( (itemsbuf[id].flags&ITEM_PASSIVESCRIPT) && (get_bit(quest_rules, qr_ITEMSCRIPTSKEEPRUNNING)) ))
3062 {
3063 ri = &(itemScriptData[id]);
3064 for ( int32_t q = 0; q < 1024; q++ ) item_stack[id][q] = 0xFFFF;
3065 ri->Clear();
3066 item_doscript[id] = 1;
3067 itemscriptInitialised[id] = 0;
3068
3069
3070 if(get_bit(quest_rules,qr_PASSIVE_ITEM_SCRIPT_ONLY_HIGHEST)
3071 && current_item(itemsbuf[id].family) > itemsbuf[id].fam_type)
3072 {
3073 item_doscript[id] = 0;
3074 return;
3075 }
3076 if(doRun)
3077 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[id].script, id);
3078 }
3079 18 }
3080
3081 // separate case for sword/wand/hammer/slashed weapons only
3082 // the main weapon checking is in the global function check_collisions()
3083 1888 bool HeroClass::checkstab()
3084 {
3085
5/14
✓ Branch 0 taken 1650 times.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 238 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 68 times.
✓ Branch 13 taken 170 times.
1888 if(action!=attacking && action!=sideswimattacking || (attack!=wSword && attack!=wWand && attack!=wHammer && attack!=wCByrna && attack!=wFire && attack != wBugNet)
3086 238 || (attackclk<=4))
3087 1718 return false;
3088
3089 170 weapon *w=NULL;
3090
3091 170 int32_t wx=0,wy=0,wz=0,wxsz=0,wysz=0;
3092 170 bool found = false;
3093 170 int32_t melee_weapon_index = 0;
3094 170 int32_t parentitem=-1;
3095 170 weapon* meleeweap = nullptr;
3096
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 211 times.
228 for(int32_t i=0; i<Lwpns.Count(); i++)
3097 {
3098 211 w = (weapon*)Lwpns.spr(i);
3099
3100
4/6
✓ Branch 0 taken 211 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 211 times.
✓ Branch 4 taken 58 times.
✓ Branch 5 taken 153 times.
211 if(w->id == (attack==wCByrna || attack==wFire ? wWand : attack)) // Kludge: Byrna and Candle sticks are wWand-type.
3101 {
3102 153 found = true;
3103 153 melee_weapon_index = i+1;
3104 153 meleeweap = w;
3105 // Position the sword as Hero slashes with it.
3106
2/4
✓ Branch 0 taken 153 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 153 times.
153 if(w->id!=wHammer&&w->id!=wBugNet)
3107 153 positionSword(w,w->parentitem);
3108
3109 153 wx=w->x;
3110 153 wy=w->y;
3111 153 wz=w->z;
3112 153 wxsz = w->hxsz;
3113 153 wysz = w->hysz;
3114 153 parentitem = w->parentitem;
3115 153 break;
3116 }
3117 58 }
3118
3119
4/6
✓ Branch 0 taken 170 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 153 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
170 if(attack==wSword && attackclk>=14 && charging==0)
3120 17 return false;
3121
3122
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 17 times.
153 if(!found)
3123 17 return false;
3124
3125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if(attack == wFire)
3126 return false;
3127
3128
1/2
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
136 if(attack==wHammer)
3129 {
3130 if(attackclk<15)
3131 {
3132 switch(w->dir)
3133 {
3134 case up:
3135 wx=x-1;
3136 wy=y-4;
3137 break;
3138
3139 case down:
3140 wx=x+8;
3141 wy=y+28;
3142 break; // This is consistent with 2.10
3143
3144 case left:
3145 wx=x-13;
3146 wy=y+14;
3147 break;
3148
3149 case right:
3150 wx=x+21;
3151 wy=y+14;
3152 break;
3153 }
3154
3155 if(attackclk==12 && z==0 && fakez==0 && sideviewhammerpound())
3156 {
3157 //decorations.add(new dHammerSmack((zfix)wx, (zfix)wy, dHAMMERSMACK, 0));
3158 /* The hammer smack sprites weren't being positioned properly if Hero changed directions on the same frame that they are created.
3159 switch(dir)
3160 {
3161 case up:
3162 decorations.add(new dHammerSmack(x-1, y-4, dHAMMERSMACK, 0));
3163 break;
3164
3165 case down:
3166 decorations.add(new dHammerSmack(x+8, y+28, dHAMMERSMACK, 0));
3167 break;
3168
3169 case left:
3170 decorations.add(new dHammerSmack(x-13, y+14, dHAMMERSMACK, 0));
3171 break;
3172
3173 case right:
3174 decorations.add(new dHammerSmack(x+21, y+14, dHAMMERSMACK, 0));
3175 break;
3176 }
3177 */
3178 }
3179
3180 return false;
3181 }
3182 else if(attackclk==15)
3183 {
3184 // Hammer's reach needs adjusted slightly for backward compatibility
3185 if(w->dir==up)
3186 w->hyofs-=1;
3187 else if(w->dir==left)
3188 w->hxofs-=2;
3189 }
3190 }
3191
3192 // The return of Spaghetti Code Constants!
3193
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
✓ Branch 2 taken 136 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
136 int32_t itype = (attack==wWand ? itype_wand : attack==wSword ? itype_sword : attack==wCByrna ? itype_cbyrna : attack==wBugNet ? itype_bugnet : itype_hammer);
3194
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
136 int32_t itemid = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype);
3195 136 itemid = vbound(itemid, 0, MAXITEMS-1);
3196
3197 // The sword offsets aren't based on anything other than what felt about right
3198 // compared to the NES game and what mostly kept it from hitting things that
3199 // should clearly be out of range. They could probably still use more tweaking.
3200 // Don't use 2.10 for reference; it's pretty far off.
3201 // - Saf
3202
3203
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
136 if(game->get_canslash() && (attack==wSword || attack==wWand) && itemsbuf[itemid].flags & ITEM_FLAG4)
3204 {
3205 switch(w->dir)
3206 {
3207 case up:
3208 if(attackclk<8)
3209 {
3210 wy-=4;
3211 }
3212
3213 break;
3214
3215 case down:
3216 //if(attackclk<8)
3217 {
3218 wy-=2;
3219 }
3220 break;
3221
3222 case left:
3223
3224 //if(attackclk<8)
3225 {
3226 wx+=2;
3227 }
3228
3229 break;
3230
3231 case right:
3232
3233 //if(attackclk<8)
3234 {
3235 wx-=3;
3236 //wy+=((spins>0 || get_bit(quest_rules, qr_SLASHFLIPFIX)) ? -4 : 4);
3237 }
3238
3239 break;
3240 }
3241 }
3242
3243
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 54 times.
✓ Branch 4 taken 58 times.
136 switch(w->dir)
3244 {
3245 case up:
3246 16 wx+=2;
3247 16 break;
3248
3249 case down:
3250 8 break;
3251
3252 case left:
3253 54 wy-=3;
3254 54 break;
3255
3256 case right:
3257 58 wy-=3;
3258 58 break;
3259 }
3260
3261 136 wx+=w->hxofs;
3262 136 wy+=w->hyofs;
3263 136 wy-=(w->fakez).getInt();
3264
3265
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 334 times.
470 for(int32_t i=0; i<guys.Count(); i++)
3266 {
3267
1/2
✓ Branch 0 taken 334 times.
✗ Branch 1 not taken.
334 if(attack==wBugNet) break;
3268 // So that Hero can actually hit peahats while jumping, his weapons' hzsz becomes 16 in midair.
3269
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 333 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
334 if((guys.spr(i)->hit(wx,wy,wz,wxsz,wysz,wz>0?16:8) && ((attack!=wWand && attack!=wHammer && attack!=wCByrna) || !(itemsbuf[itemid].flags & ITEM_FLAG3)))
3270
2/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 333 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 333 times.
333 || ((attack==wWand || attack==wCByrna) && guys.spr(i)->hit(wx,wy-8,z,16,24,z>8) && !(itemsbuf[itemid].flags & ITEM_FLAG3))
3271
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
333 || (attack==wHammer && guys.spr(i)->hit(wx,wy-8,z,16,24,z>0?16:8) && !(itemsbuf[itemid].flags & ITEM_FLAG3)))
3272 {
3273 // Checking the whimsical ring for every collision check causes
3274 // an odd bug. It's much more likely to activate on a 0-damage
3275 // weapon, since a 0-damage hit won't make the enemy invulnerable
3276 // to damaging hits in the following frames.
3277
3278 1 int32_t whimsyid = current_item_id(itype_whimsicalring);
3279
3280 1 int32_t dmg = weaponattackpower(itemid);
3281
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(whimsyid>-1)
3282 {
3283 if(!(zc_oldrand()%zc_max(itemsbuf[whimsyid].misc1,1)))
3284 dmg += current_item_power(itype_whimsicalring);
3285 else whimsyid = -1;
3286 }
3287 1 int32_t atkringid = current_item_id(itype_atkring);
3288
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(atkringid>-1)
3289 {
3290 dmg *= itemsbuf[atkringid].misc2; //Multiplier
3291 dmg += itemsbuf[atkringid].misc1; //Additive
3292 }
3293
3294 1 int32_t h = hit_enemy(i,attack,dmg*game->get_hero_dmgmult(),wx,wy,dir,directWpn);
3295 1 enemy *e = (enemy*)guys.spr(i);
3296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (h == -1) { e->hitby[HIT_BY_LWEAPON] = melee_weapon_index; } //temp_hit = true; }
3297 //melee weapons and non-melee weapons both writing to this index may be a problem. It needs to be cleared by something earlier than this check.
3298
3299
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if(h<0 && whimsyid>-1)
3300 {
3301 sfx(itemsbuf[whimsyid].usesound);
3302 }
3303
3304
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if(h && charging>0)
3305 {
3306 attackclk = SWORDTAPFRAME;
3307 spins=0;
3308 }
3309
3310
4/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 if(h && hclk==0 && inlikelike != 1 && !get_bit(quest_rules, qr_DYING_ENEMIES_IGNORE_STUN))
3311 {
3312
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(GuyHit(i,x+7,y+7-fakez,z,2,2,hzsz)!=-1)
3313 {
3314 hithero(i);
3315 }
3316 1 }
3317
3318
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(h==2)
3319 break;
3320 1 }
3321 334 }
3322
3323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
272 if(attack == wBugNet
3324
2/4
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 136 times.
136 || (parentitem==-1&&!get_bit(quest_rules,qr_NOITEMMELEE))
3325
1/2
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
136 || (parentitem>-1&&!(itemsbuf[parentitem].flags & ITEM_FLAG7)))
3326 {
3327
1/4
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
136 int32_t bugnetid = attack != wBugNet ? -1 : (parentitem > -1 ? parentitem : current_item_id(itype_bugnet));
3328
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 86 times.
222 for(int32_t j=0; j<items.Count(); j++)
3329 {
3330 86 item* ptr = (item*)items.spr(j);
3331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 bool dofairy = (attack==wBugNet && itemsbuf[ptr->id].family == itype_fairy)
3332 && (bugnetid > -1 && !(itemsbuf[bugnetid].flags & ITEM_FLAG1));
3333
3334
2/4
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 86 times.
✗ Branch 3 not taken.
86 if((itemsbuf[ptr->id].family == itype_bottlefill || dofairy) && !game->canFillBottle())
3335 continue; //No picking these up unless you have a bottle to fill!
3336
2/6
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 86 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
86 if((ptr->pickup & ipCANGRAB) || (ptr->pickup & ipTIMER) || dofairy)
3337 {
3338
6/8
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 64 times.
✓ Branch 5 taken 22 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 64 times.
86 if(((ptr->pickup & ipCANGRAB) || ptr->clk2 >= 32 || dofairy) && !ptr->fallclk && !ptr->drownclk)
3339 {
3340
3/6
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
128 if(ptr->hit(wx,wy,z,wxsz,wysz,1) || (attack==wWand && ptr->hit(x,y-8-fakez,z,wxsz,wysz,1))
3341
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
64 || (attack==wHammer && ptr->hit(x,y-8-fakez,z,wxsz,wysz,1)))
3342 {
3343 int32_t pickup = ptr->pickup;
3344 int32_t id2 = ptr->id;
3345 int32_t pstr = ptr->pstring;
3346 int32_t pstr_flags = ptr->pickup_string_flags;
3347 if(!dofairy)
3348 {
3349 std::vector<int32_t> &ev = FFCore.eventData;
3350 ev.clear();
3351 ev.push_back(id2*10000);
3352 ev.push_back(pickup*10000);
3353 ev.push_back(pstr*10000);
3354 ev.push_back(pstr_flags*10000);
3355 ev.push_back(0);
3356 ev.push_back(ptr->getUID());
3357 ev.push_back(GENEVT_ICTYPE_MELEE*10000);
3358 ev.push_back(w->getUID());
3359
3360 throwGenScriptEvent(GENSCR_EVENT_COLLECT_ITEM);
3361 bool nullify = ev[4] != 0;
3362 if(nullify) continue;
3363 id2 = ev[0]/10000;
3364 pickup = (pickup&(ipCHECK|ipDUMMY)) | (ev[1]/10000);
3365 pstr = ev[2] / 10000;
3366 pstr_flags = ev[3] / 10000;
3367 }
3368
3369 if(pickup&ipONETIME) // set mITEM for one-time-only items
3370 setmapflag(mITEM);
3371 else if(pickup&ipONETIME2) // set mSPECIALITEM flag for other one-time-only items
3372 setmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM);
3373
3374 if(ptr->pickupexstate > -1 && ptr->pickupexstate < 32)
3375 setxmapflag(1<<ptr->pickupexstate);
3376 if(pickup&ipSECRETS) // Trigger secrets if this item has the secret pickup
3377 {
3378 if(tmpscr->flags9&fITEMSECRETPERM) setmapflag(mSECRET);
3379 hidden_entrance(0, true, false, -5);
3380 }
3381 //!DIMI
3382
3383 if(dofairy)
3384 {
3385 game->fillBottle(itemsbuf[ptr->id].misc4);
3386 }
3387 else
3388 {
3389 collectitem_script(id2);
3390
3391 getitem(id2, false, true);
3392 }
3393 items.del(j);
3394
3395 for(int32_t i=0; i<Lwpns.Count(); i++)
3396 {
3397 weapon *w2 = (weapon*)Lwpns.spr(i);
3398
3399 if(w2->dragging==j)
3400 {
3401 w2->dragging=-1;
3402 }
3403 else if(w2->dragging>j)
3404 {
3405 w2->dragging-=1;
3406 }
3407 }
3408
3409 if ( (pstr > 0 && pstr < msg_count) )
3410 {
3411 if ( ( (!(pstr_flags&itemdataPSTRING_IP_HOLDUP)) && ( pstr_flags&itemdataPSTRING_NOMARK || pstr_flags&itemdataPSTRING_ALWAYS || (!(FFCore.GetItemMessagePlayed(id2))) ) ) )
3412 {
3413 if ( (!(pstr_flags&itemdataPSTRING_NOMARK)) )
3414 FFCore.SetItemMessagePlayed(id2);
3415 donewmsg(pstr);
3416 break;
3417 }
3418 }
3419
3420 --j;
3421 }
3422 64 }
3423 86 }
3424 86 }
3425 136 }
3426
3427
2/4
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 136 times.
136 if(attack==wCByrna || attack==wBugNet)
3428 return false;
3429
3430
1/2
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
136 if(attack==wSword)
3431 {
3432
2/2
✓ Branch 0 taken 119 times.
✓ Branch 1 taken 17 times.
136 if(attackclk == 6)
3433 {
3434
2/2
✓ Branch 0 taken 2992 times.
✓ Branch 1 taken 17 times.
3009 for(int32_t q=0; q<176; q++)
3435 {
3436 2992 set_bit(screengrid,q,0);
3437 2992 set_bit(screengrid_layer[0],q,0);
3438 2992 set_bit(screengrid_layer[1],q,0);
3439
3440 2992 }
3441
3442
2/2
✓ Branch 0 taken 272 times.
✓ Branch 1 taken 17 times.
289 for(dword q = MAXFFCS/8; q > 0; --q)
3443 272 ffcgrid[q-1] = 0;
3444 17 }
3445
3446
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
136 if(dir==up && ((x.getInt()&15)==0))
3447 {
3448 16 check_slash_block(wx,wy);
3449 16 check_slash_block(wx,wy+8);
3450
3451 //layers
3452 16 check_slash_block_layer(wx,wy,1);
3453 16 check_slash_block_layer(wx,wy+8,1);
3454 16 check_slash_block_layer(wx,wy,1);
3455 16 check_slash_block_layer(wx,wy+8,1);
3456 //2
3457 16 check_slash_block_layer(wx,wy,2);
3458 16 check_slash_block_layer(wx,wy+8,2);
3459 16 check_slash_block_layer(wx,wy,2);
3460 16 check_slash_block_layer(wx,wy+8,2);
3461
3462
3463
3464 16 }
3465
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
120 else if(dir==up && ((x.getInt()&15)==8||diagonalMovement||NO_GRIDLOCK))
3466 {
3467 check_slash_block(wx,wy);
3468 check_slash_block(wx,wy+8);
3469 check_slash_block(wx+8,wy);
3470 check_slash_block(wx+8,wy+8);
3471 ///layer 1
3472 check_slash_block_layer(wx,wy,1);
3473 check_slash_block_layer(wx,wy+8,1);
3474 check_slash_block_layer(wx+8,wy,1);
3475 check_slash_block_layer(wx+8,wy+8,1);
3476 ///layer 2
3477 check_slash_block_layer(wx,wy,2);
3478 check_slash_block_layer(wx,wy+8,2);
3479 check_slash_block_layer(wx+8,wy,2);
3480 check_slash_block_layer(wx+8,wy+8,2);
3481 }
3482
3483
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 128 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
136 if(dir==down && ((x.getInt()&15)==0))
3484 {
3485 8 check_slash_block(wx,wy+wysz-8);
3486 8 check_slash_block(wx,wy+wysz);
3487
3488 //layer 1
3489 8 check_slash_block_layer(wx,wy+wysz-8,1);
3490 8 check_slash_block_layer(wx,wy+wysz,1);
3491 //layer 2
3492 8 check_slash_block_layer(wx,wy+wysz-8,2);
3493 8 check_slash_block_layer(wx,wy+wysz,2);
3494 8 }
3495
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
128 else if(dir==down && ((x.getInt()&15)==8||diagonalMovement||NO_GRIDLOCK))
3496 {
3497 check_slash_block(wx,wy+wysz-8);
3498 check_slash_block(wx,wy+wysz);
3499 check_slash_block(wx+8,wy+wysz-8);
3500 check_slash_block(wx+8,wy+wysz);
3501 //layer 1
3502 check_slash_block_layer(wx,wy+wysz-8,1);
3503 check_slash_block_layer(wx,wy+wysz,1);
3504 check_slash_block_layer(wx+8,wy+wysz-8,1);
3505 check_slash_block_layer(wx+8,wy+wysz,1);
3506 //layer 2
3507 check_slash_block_layer(wx,wy+wysz-8,2);
3508 check_slash_block_layer(wx,wy+wysz,2);
3509 check_slash_block_layer(wx+8,wy+wysz-8,2);
3510 check_slash_block_layer(wx+8,wy+wysz,2);
3511 }
3512
3513
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 54 times.
136 if(dir==left)
3514 {
3515 54 check_slash_block(wx,wy+8);
3516 54 check_slash_block(wx+8,wy+8);
3517 //layer 1
3518 54 check_slash_block_layer(wx,wy+8,1);
3519 54 check_slash_block_layer(wx+8,wy+8,1);
3520 //layer 2
3521 54 check_slash_block_layer(wx,wy+8,2);
3522 54 check_slash_block_layer(wx+8,wy+8,2);
3523 54 }
3524
3525
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 58 times.
136 if(dir==right)
3526 {
3527 58 check_slash_block(wx+wxsz,wy+8);
3528 58 check_slash_block(wx+wxsz-8,wy+8);
3529 //layer 1
3530 58 check_slash_block_layer(wx+wxsz,wy+8,1);
3531 58 check_slash_block_layer(wx+wxsz-8,wy+8,1);
3532 //layer 2
3533 58 check_slash_block_layer(wx+wxsz,wy+8,2);
3534 58 check_slash_block_layer(wx+wxsz-8,wy+8,2);
3535 58 }
3536 136 }
3537 else if(attack==wWand)
3538 {
3539 if(attackclk == 5)
3540 {
3541 for(int32_t q=0; q<176; q++)
3542 {
3543 set_bit(screengrid,q,0);
3544 set_bit(screengrid_layer[0],q,0);
3545 set_bit(screengrid_layer[1],q,0);
3546 }
3547
3548 for(dword q = MAXFFCS/8; q > 0; --q)
3549 ffcgrid[q-1] = 0;
3550 }
3551
3552 // cutable blocks
3553 if(dir==up && (x.getInt()&15)==0)
3554 {
3555 check_wand_block(wx,wy);
3556 check_wand_block(wx,wy+8);
3557 }
3558 else if(dir==up && ((x.getInt()&15)==8||diagonalMovement||NO_GRIDLOCK))
3559 {
3560 check_wand_block(wx,wy);
3561 check_wand_block(wx,wy+8);
3562 check_wand_block(wx+8,wy);
3563 check_wand_block(wx+8,wy+8);
3564 }
3565
3566 if(dir==down && (x.getInt()&15)==0)
3567 {
3568 check_wand_block(wx,wy+wysz-8);
3569 check_wand_block(wx,wy+wysz);
3570 }
3571 else if(dir==down && ((x.getInt()&15)==8||diagonalMovement||NO_GRIDLOCK))
3572 {
3573 check_wand_block(wx,wy+wysz-8);
3574 check_wand_block(wx,wy+wysz);
3575 check_wand_block(wx+8,wy+wysz-8);
3576 check_wand_block(wx+8,wy+wysz);
3577 }
3578
3579 if(dir==left)
3580 {
3581 check_wand_block(wx,y+8);
3582 check_wand_block(wx+8,y+8);
3583 }
3584
3585 if(dir==right)
3586 {
3587 check_wand_block(wx+wxsz,y+8);
3588 check_wand_block(wx+wxsz-8,y+8);
3589 }
3590 }
3591 else if((attack==wHammer) && ((attackclk==15) || ( spins==1 && attackclk >=15 ))) //quake hammer should be spins == 1
3592 //else if((attack==wHammer) && (attackclk==15))
3593 //reverting this, because it breaks multiple-hit pegs
3594 //else if((attack==wHammer) && (attackclk>=15)) //>= instead of == for time it takes to charge up hammer with quake scrolls.
3595 {
3596 // poundable blocks
3597 for(int32_t q=0; q<176; q++)
3598 {
3599 set_bit(screengrid,q,0);
3600 set_bit(screengrid_layer[0],q,0);
3601 set_bit(screengrid_layer[1],q,0);
3602 }
3603
3604 for(dword q = MAXFFCS/8; q > 0; --q)
3605 ffcgrid[q-1] = 0;
3606
3607 if(dir==up && (x.getInt()&15)==0)
3608 {
3609 check_pound_block(wx,wy);
3610 check_pound_block(wx,wy+8);
3611 }
3612 else if(dir==up && ((x.getInt()&15)==8||diagonalMovement||NO_GRIDLOCK))
3613 {
3614 check_pound_block(wx,wy);
3615 check_pound_block(wx,wy+8);
3616 check_pound_block(wx+8,wy);
3617 check_pound_block(wx+8,wy+8);
3618 }
3619
3620 if(dir==down && (x.getInt()&15)==0)
3621 {
3622 check_pound_block(wx,wy+wysz-8);
3623 check_pound_block(wx,wy+wysz);
3624 }
3625 else if(dir==down && ((x.getInt()&15)==8||diagonalMovement||NO_GRIDLOCK))
3626 {
3627 check_pound_block(wx,wy+wysz-8);
3628 check_pound_block(wx,wy+wysz);
3629 check_pound_block(wx+8,wy+wysz-8);
3630 check_pound_block(wx+8,wy+wysz);
3631 }
3632
3633 if(dir==left)
3634 {
3635 check_pound_block(wx,y+8);
3636 check_pound_block(wx+8,y+8);
3637 }
3638
3639 if(dir==right)
3640 {
3641 check_pound_block(wx+wxsz,y+8);
3642 check_pound_block(wx+wxsz-8,y+8);
3643 }
3644 }
3645 else
3646 {
3647 return false;
3648 }
3649
3650 136 return true;
3651 1888 }
3652
3653 608 void HeroClass::check_slash_block_layer(int32_t bx, int32_t by, int32_t layer)
3654 {
3655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if(!(get_bit(quest_rules,qr_BUSHESONLAYERS1AND2)))
3656 {
3657 //zprint("bit off\n");
3658 608 return;
3659 }
3660 //keep things inside the screen boundaries
3661 bx=vbound(bx, 0, 255);
3662 by=vbound(by, 0, 176);
3663 int32_t fx=vbound(bx, 0, 255);
3664 int32_t fy=vbound(by, 0, 176);
3665 //first things first
3666 if(attack!=wSword)
3667 return;
3668
3669 if(z>8||fakez>8 || attackclk==SWORDCHARGEFRAME // is not charging>0, as tapping a wall reduces attackclk but retains charging
3670 || (attackclk>SWORDTAPFRAME && tapping))
3671 return;
3672
3673 //find out which combo row/column the coordinates are in
3674 bx &= 0xF0;
3675 by &= 0xF0;
3676
3677
3678 int32_t flag = MAPFLAGL(layer,bx,by);
3679 int32_t flag2 = MAPCOMBOFLAGL(layer,bx,by);
3680 int32_t cid = MAPCOMBOL(layer,bx,by);
3681 int32_t type = combobuf[cid].type;
3682 if(combobuf[cid].triggerflags[0] & combotriggerONLYGENTRIG)
3683 type = cNONE;
3684 //zprint("cid is: %d\n", cid);
3685 //zprint("type is: %d\n", type);
3686 int32_t i = (bx>>4) + by;
3687
3688 if(i > 175)
3689 return;
3690
3691 bool ignorescreen=false;
3692
3693 if((get_bit(screengrid_layer[layer-1], i) != 0) || (!isCuttableType(type)))
3694 return;
3695
3696 int32_t sworditem = (directWpn>-1 && itemsbuf[directWpn].family==itype_sword) ? itemsbuf[directWpn].fam_type : current_item(itype_sword);
3697
3698 if(!isTouchyType(type) && !get_bit(quest_rules, qr_CONT_SWORD_TRIGGERS)) set_bit(screengrid_layer[layer-1],i,1);
3699 if(isCuttableNextType(type))
3700 {
3701 FFCore.tempScreens[layer]->data[i]++;
3702 }
3703 else
3704 {
3705 FFCore.tempScreens[layer]->data[i] = tmpscr->undercombo;
3706 FFCore.tempScreens[layer]->cset[i] = tmpscr->undercset;
3707 FFCore.tempScreens[layer]->sflag[i] = 0;
3708 }
3709 if((flag==mfARMOS_ITEM||flag2==mfARMOS_ITEM) && (!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN)))
3710 {
3711 items.add(new item((zfix)bx, (zfix)by,(zfix)0, tmpscr->catchall, ipONETIME2 + ipBIGRANGE + ipHOLDUP | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0), 0));
3712 sfx(tmpscr->secretsfx);
3713 }
3714 else if(isCuttableItemType(type))
3715 {
3716 int32_t it = -1;
3717 int32_t thedropset = -1;
3718
3719 //select_dropitem( (combobuf[MAPCOMBO(bx,by)-1].usrflags&cflag2) ? (combobuf[MAPCOMBO(bx,by)-1].attributes[1])/10000L : 12, bx, by);
3720 if ( (combobuf[cid].usrflags&cflag2) )
3721 {
3722 if(combobuf[cid].usrflags&cflag11)
3723 it = combobuf[cid].attribytes[1];
3724 else
3725 {
3726 it = select_dropitem(combobuf[cid].attribytes[1]);
3727 thedropset = combobuf[cid].attribytes[1];
3728 }
3729 }
3730 else
3731 {
3732 it = select_dropitem(12);
3733 thedropset = 12;
3734 }
3735 if(it!=-1)
3736 {
3737 item* itm = (new item((zfix)bx, (zfix)by,(zfix)0, it, ipBIGRANGE + ipTIMER, 0));
3738 itm->from_dropset = thedropset;
3739 items.add(itm);
3740 }
3741 }
3742
3743 putcombo(scrollbuf,(i&15)<<4,i&0xF0,tmpscr->data[i],tmpscr->cset[i]);
3744
3745 if(get_bit(quest_rules,qr_MORESOUNDS))
3746 {
3747 if (!isBushType(type) && !isFlowersType(type) && !isGrassType(type))
3748 {
3749 if (combobuf[cid].usrflags&cflag3)
3750 {
3751 sfx(combobuf[cid].attribytes[2],int32_t(bx));
3752 }
3753 }
3754 else
3755 {
3756 if (combobuf[cid].usrflags&cflag3)
3757 {
3758 sfx(combobuf[cid].attribytes[2],int32_t(bx));
3759 }
3760 else sfx(QMisc.miscsfx[sfxBUSHGRASS],int32_t(bx));
3761 }
3762 }
3763
3764 int16_t decotype = (combobuf[cid].usrflags & cflag1) ? ((combobuf[cid].usrflags & cflag10) ? (combobuf[cid].attribytes[0]) : (-1)) : (0);
3765 if(decotype > 3) decotype = 0;
3766 if(!decotype) decotype = (isBushType(type) ? 1 : (isFlowersType(type) ? 2 : (isGrassType(type) ? 3 : ((combobuf[cid].usrflags & cflag1) ? -1 : -2))));
3767 switch(decotype)
3768 {
3769 case -2: break; //nothing
3770 case -1:
3771 decorations.add(new comboSprite((zfix)fx, (zfix)fy, 0, 0, combobuf[cid].attribytes[0]));
3772 break;
3773 case 1: decorations.add(new dBushLeaves((zfix)fx, (zfix)fy, dBUSHLEAVES, 0, 0)); break;
3774 case 2: decorations.add(new dFlowerClippings((zfix)fx, (zfix)fy, dFLOWERCLIPPINGS, 0, 0)); break;
3775 case 3: decorations.add(new dGrassClippings((zfix)fx, (zfix)fy, dGRASSCLIPPINGS, 0, 0)); break;
3776 }
3777 608 }
3778
3779 272 void HeroClass::check_slash_block(int32_t bx, int32_t by)
3780 {
3781 //keep things inside the screen boundaries
3782 272 bx=vbound(bx, 0, 255);
3783 272 by=vbound(by, 0, 176);
3784 272 int32_t fx=vbound(bx, 0, 255);
3785 272 int32_t fy=vbound(by, 0, 176);
3786 //first things first
3787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 272 times.
272 if(attack!=wSword)
3788 return;
3789
3790
3/6
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 272 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 34 times.
306 if(z>8||fakez>8 || attackclk==SWORDCHARGEFRAME // is not charging>0, as tapping a wall reduces attackclk but retains charging
3791
3/4
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 238 times.
272 || (attackclk>SWORDTAPFRAME && tapping))
3792 return;
3793
3794 //find out which combo row/column the coordinates are in
3795 272 bx &= 0xF0;
3796 272 by &= 0xF0;
3797
3798 272 int32_t type = COMBOTYPE(bx,by);
3799 272 int32_t type2 = FFCOMBOTYPE(fx,fy);
3800 272 int32_t flag = MAPFLAG(bx,by);
3801 272 int32_t flag2 = MAPCOMBOFLAG(bx,by);
3802 272 int32_t flag3 = MAPFFCOMBOFLAG(fx,fy);
3803 272 int32_t cid = MAPCOMBO(bx,by);
3804 272 int32_t i = (bx>>4) + by;
3805
3806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 272 times.
272 if(i > 175)
3807 return;
3808
3809 272 bool ignorescreen=false;
3810 272 bool ignoreffc=false;
3811
3812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 272 times.
272 if(get_bit(screengrid, i) != 0)
3813 {
3814 ignorescreen = true;
3815 }
3816
1/2
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
272 else if(combobuf[cid].triggerflags[0] & combotriggerONLYGENTRIG)
3817 ignorescreen = true;
3818
3819 272 int32_t current_ffcombo = getFFCAt(fx,fy);
3820
3821
3822
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 272 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
272 if(current_ffcombo == -1 || get_bit(ffcgrid, current_ffcombo) != 0)
3823 {
3824 272 ignoreffc = true;
3825 272 }
3826 else if(combobuf[tmpscr->ffcs[current_ffcombo].getData()].triggerflags[0] & combotriggerONLYGENTRIG)
3827 ignoreffc = true;
3828
3829
2/4
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 272 times.
544 if(!isCuttableType(type) &&
3830
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 272 times.
✓ Branch 2 taken 272 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 272 times.
272 (flag<mfSWORD || flag>mfXSWORD) && flag!=mfSTRIKE && (flag2<mfSWORD || flag2>mfXSWORD) && flag2!=mfSTRIKE)
3831 {
3832 272 ignorescreen = true;
3833 272 }
3834
3835
2/4
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 272 times.
544 if(!isCuttableType(type2) &&
3836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 272 times.
272 (flag3<mfSWORD || flag3>mfXSWORD) && flag3!=mfSTRIKE)
3837 {
3838 272 ignoreffc = true;
3839 272 }
3840
3841 272 mapscr *s = tmpscr + ((currscr>=128) ? 1 : 0);
3842
3843
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 272 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
272 int32_t sworditem = (directWpn>-1 && itemsbuf[directWpn].family==itype_sword) ? itemsbuf[directWpn].fam_type : current_item(itype_sword);
3844 272 byte skipsecrets = 0;
3845
3846
1/2
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
272 if ( isNextType(type) ) //->Next combos should not trigger secrets. Their child combo, may want to do that! -Z 17th December, 2019
3847 {
3848 if (get_bit(quest_rules,qr_OLD_SLASHNEXT_SECRETS))
3849 {
3850 skipsecrets = 0;
3851 }
3852 else skipsecrets = 1; ;
3853 }
3854
3855
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 272 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
272 if(!ignorescreen && (!skipsecrets || !get_bit(quest_rules,qr_BUGGY_BUGGY_SLASH_TRIGGERS)))
3856 {
3857 if((flag >= 16)&&(flag <= 31) && !skipsecrets)
3858 {
3859 s->data[i] = s->secretcombo[(s->sflag[i])-16+4];
3860 s->cset[i] = s->secretcset[(s->sflag[i])-16+4];
3861 s->sflag[i] = s->secretflag[(s->sflag[i])-16+4];
3862 }
3863 else if(flag == mfARMOS_SECRET)
3864 {
3865 s->data[i] = s->secretcombo[sSTAIRS];
3866 s->cset[i] = s->secretcset[sSTAIRS];
3867 s->sflag[i] = s->secretflag[sSTAIRS];
3868 sfx(tmpscr->secretsfx);
3869 }
3870 else if(((flag>=mfSWORD&&flag<=mfXSWORD)||(flag==mfSTRIKE)))
3871 {
3872 for(int32_t i2=0; i2<=zc_min(sworditem-1,3); i2++)
3873 {
3874 findentrance(bx,by,mfSWORD+i2,true);
3875 }
3876
3877 findentrance(bx,by,mfSTRIKE,true);
3878 }
3879 else if(((flag2 >= 16)&&(flag2 <= 31)))
3880 {
3881 s->data[i] = s->secretcombo[(s->sflag[i])-16+4];
3882 s->cset[i] = s->secretcset[(s->sflag[i])-16+4];
3883 s->sflag[i] = s->secretflag[(s->sflag[i])-16+4];
3884 }
3885 else if(flag2 == mfARMOS_SECRET)
3886 {
3887 s->data[i] = s->secretcombo[sSTAIRS];
3888 s->cset[i] = s->secretcset[sSTAIRS];
3889 s->sflag[i] = s->secretflag[sSTAIRS];
3890 sfx(tmpscr->secretsfx);
3891 }
3892 else if(((flag2>=mfSWORD&&flag2<=mfXSWORD)||(flag2==mfSTRIKE)))
3893 {
3894 for(int32_t i2=0; i2<=zc_min(sworditem-1,3); i2++)
3895 {
3896 findentrance(bx,by,mfSWORD+i2,true);
3897 }
3898
3899 findentrance(bx,by,mfSTRIKE,true);
3900 }
3901 else
3902 {
3903 if(isCuttableNextType(type))
3904 {
3905 s->data[i]++;
3906 }
3907 else
3908 {
3909 s->data[i] = s->undercombo;
3910 s->cset[i] = s->undercset;
3911 s->sflag[i] = 0;
3912 }
3913
3914 //pausenow=true;
3915 }
3916 }
3917
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 272 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
272 else if(!ignorescreen && skipsecrets)
3918 {
3919 if(isCuttableNextType(type))
3920 {
3921 s->data[i]++;
3922 }
3923 else
3924 {
3925 s->data[i] = s->undercombo;
3926 s->cset[i] = s->undercset;
3927 s->sflag[i] = 0;
3928 }
3929 }
3930
3931
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 272 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 272 times.
272 if(((flag3>=mfSWORD&&flag3<=mfXSWORD)||(flag3==mfSTRIKE)) && !ignoreffc)
3932 {
3933 for(int32_t i2=0; i2<=zc_min(sworditem-1,3); i2++)
3934 {
3935 findentrance(bx,by,mfSWORD+i2,true);
3936 }
3937
3938 findentrance(fx,fy,mfSTRIKE,true);
3939 }
3940
1/2
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
272 else if(!ignoreffc)
3941 {
3942 if(isCuttableNextType(type2))
3943 {
3944 s->ffcs[current_ffcombo].incData(1);
3945 }
3946 else
3947 {
3948 s->ffcs[current_ffcombo].setData(s->undercombo);
3949 s->ffcs[current_ffcombo].cset = s->undercset;
3950 }
3951 }
3952
3953
1/2
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
272 if(!ignorescreen)
3954 {
3955 if(!isTouchyType(type) && !get_bit(quest_rules, qr_CONT_SWORD_TRIGGERS)) set_bit(screengrid,i,1);
3956
3957 if((flag==mfARMOS_ITEM||flag2==mfARMOS_ITEM) && (!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN)))
3958 {
3959 items.add(new item((zfix)bx, (zfix)by,(zfix)0, tmpscr->catchall, ipONETIME2 + ipBIGRANGE + ipHOLDUP | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0), 0));
3960 sfx(tmpscr->secretsfx);
3961 }
3962 else if(isCuttableItemType(type))
3963 {
3964 int32_t it = -1;
3965 int32_t thedropset = -1;
3966 if ( (combobuf[cid].usrflags&cflag2) ) //specific dropset or item
3967 {
3968 if ( combobuf[cid].usrflags&cflag11 )
3969 {
3970 it = combobuf[cid].attribytes[1];
3971 }
3972 else
3973 {
3974 it = select_dropitem(combobuf[cid].attribytes[1]);
3975 thedropset = combobuf[cid].attribytes[1];
3976 }
3977 }
3978 else
3979 {
3980 it = select_dropitem(12);
3981 thedropset = 12;
3982 }
3983
3984 if(it!=-1)
3985 {
3986 item* itm = (new item((zfix)bx, (zfix)by,(zfix)0, it, ipBIGRANGE + ipTIMER, 0));
3987 itm->from_dropset = thedropset;
3988 items.add(itm);
3989 }
3990 }
3991
3992 putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]);
3993
3994 if(get_bit(quest_rules,qr_MORESOUNDS))
3995 {
3996 if (!isBushType(type) && !isFlowersType(type) && !isGrassType(type))
3997 {
3998 if (combobuf[cid].usrflags&cflag3)
3999 {
4000 sfx(combobuf[cid].attribytes[2],int32_t(bx));
4001 }
4002 }
4003 else
4004 {
4005 if (combobuf[cid].usrflags&cflag3)
4006 {
4007 sfx(combobuf[cid].attribytes[2],int32_t(bx));
4008 }
4009 else sfx(QMisc.miscsfx[sfxBUSHGRASS],int32_t(bx));
4010 }
4011 }
4012
4013 int16_t decotype = (combobuf[cid].usrflags & cflag1) ? ((combobuf[cid].usrflags & cflag10) ? (combobuf[cid].attribytes[0]) : (-1)) : (0);
4014 if(decotype > 3) decotype = 0;
4015 if(!decotype) decotype = (isBushType(type) ? 1 : (isFlowersType(type) ? 2 : (isGrassType(type) ? 3 : ((combobuf[cid].usrflags & cflag1) ? -1 : -2))));
4016 switch(decotype)
4017 {
4018 case -2: break; //nothing
4019 case -1:
4020 decorations.add(new comboSprite((zfix)fx, (zfix)fy, 0, 0, combobuf[cid].attribytes[0]));
4021 break;
4022 case 1: decorations.add(new dBushLeaves((zfix)fx, (zfix)fy, dBUSHLEAVES, 0, 0)); break;
4023 case 2: decorations.add(new dFlowerClippings((zfix)fx, (zfix)fy, dFLOWERCLIPPINGS, 0, 0)); break;
4024 case 3: decorations.add(new dGrassClippings((zfix)fx, (zfix)fy, dGRASSCLIPPINGS, 0, 0)); break;
4025 }
4026 }
4027
4028
1/2
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
272 if(!ignoreffc)
4029 {
4030 if(!isTouchyType(type2) && !get_bit(quest_rules, qr_CONT_SWORD_TRIGGERS)) set_bit(ffcgrid, current_ffcombo, 1);
4031
4032 if(isCuttableItemType(type2))
4033 {
4034 int32_t it=-1;
4035 int32_t thedropset=-1;
4036 if ( (combobuf[cid].usrflags&cflag2) )
4037 {
4038 if(combobuf[cid].usrflags&cflag11)
4039 it = combobuf[cid].attribytes[1];
4040 else
4041 {
4042 it = select_dropitem(combobuf[cid].attribytes[1]);
4043 thedropset = combobuf[cid].attribytes[1];
4044 }
4045 }
4046 else
4047 {
4048 int32_t r=zc_oldrand()%100;
4049
4050 if(r<15)
4051 {
4052 it=iHeart; // 15%
4053 }
4054 else if(r<35)
4055 {
4056 it=iRupy; // 20%
4057 }
4058 }
4059
4060 if(it!=-1 && itemsbuf[it].family != itype_misc) // Don't drop non-gameplay items
4061 {
4062 item* itm = (new item((zfix)fx, (zfix)fy,(zfix)0, it, ipBIGRANGE + ipTIMER, 0));
4063 itm->from_dropset = thedropset;
4064 items.add(itm);
4065 }
4066 }
4067
4068 if(get_bit(quest_rules,qr_MORESOUNDS))
4069 {
4070 if (!isBushType(type2) && !isFlowersType(type2) && !isGrassType(type2))
4071 {
4072 if (combobuf[cid].usrflags&cflag3)
4073 {
4074 sfx(combobuf[cid].attribytes[2],int32_t(bx));
4075 }
4076 }
4077 else
4078 {
4079 if (combobuf[cid].usrflags&cflag3)
4080 {
4081 sfx(combobuf[cid].attribytes[2],int32_t(bx));
4082 }
4083 else sfx(QMisc.miscsfx[sfxBUSHGRASS],int32_t(bx));
4084 }
4085 }
4086
4087 int16_t decotype = (combobuf[cid].usrflags & cflag1) ? ((combobuf[cid].usrflags & cflag10) ? (combobuf[cid].attribytes[0]) : (-1)) : (0);
4088 if(decotype > 3) decotype = 0;
4089 if(!decotype) decotype = (isBushType(type2) ? 1 : (isFlowersType(type2) ? 2 : (isGrassType(type2) ? 3 : ((combobuf[cid].usrflags & cflag1) ? -1 : -2))));
4090 switch(decotype)
4091 {
4092 case -2: break; //nothing
4093 case -1:
4094 decorations.add(new comboSprite((zfix)fx, (zfix)fy, 0, 0, combobuf[cid].attribytes[0]));
4095 break;
4096 case 1: decorations.add(new dBushLeaves((zfix)fx, (zfix)fy, dBUSHLEAVES, 0, 0)); break;
4097 case 2: decorations.add(new dFlowerClippings((zfix)fx, (zfix)fy, dFLOWERCLIPPINGS, 0, 0)); break;
4098 case 3: decorations.add(new dGrassClippings((zfix)fx, (zfix)fy, dGRASSCLIPPINGS, 0, 0)); break;
4099 }
4100 }
4101 272 }
4102
4103 3072 void HeroClass::check_wpn_triggers(int32_t bx, int32_t by, weapon *w)
4104 {
4105 /*
4106 int32_t par_item = w->parentitem;
4107 al_trace("check_wpn_triggers(weapon *w): par_item is: %d\n", par_item);
4108 int32_t usewpn = -1;
4109 if ( par_item > -1 )
4110 {
4111 usewpn = itemsbuf[par_item].useweapon;
4112 }
4113 else if ( par_item == -1 && w->ScriptGenerated )
4114 {
4115 usewpn = w->useweapon;
4116 }
4117 al_trace("check_wpn_triggers(weapon *w): usewpn is: %d\n", usewpn);
4118
4119 */
4120 3072 bx=vbound(bx, 0, 255);
4121 3072 by=vbound(by, 0, 176);
4122 3072 int32_t cid = MAPCOMBO(bx,by);
4123
1/30
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 3072 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
3072 switch(w->useweapon)
4124 {
4125 case wArrow:
4126 findentrance(bx,by,mfARROW,true);
4127 findentrance(bx,by,mfSARROW,true);
4128 findentrance(bx,by,mfGARROW,true);
4129 break;
4130 case wBeam:
4131 for(int32_t i = 0; i <4; i++) findentrance(bx,by,mfSWORDBEAM+i,true);
4132 break;
4133 case wHookshot:
4134 findentrance(bx,by,mfHOOKSHOT,true);
4135 break;
4136 case wBrang:
4137 for(int32_t i = 0; i <3; i++) findentrance(bx,by,mfBRANG+i,true);
4138 break;
4139 case wMagic:
4140 findentrance(bx,by,mfWANDMAGIC,true);
4141 break;
4142 case wRefMagic:
4143 findentrance(bx,by,mfWANDMAGIC,true);
4144 break;
4145 case wRefBeam:
4146 for(int32_t i = 0; i <4; i++) findentrance(bx,by,mfSWORDBEAM+i,true);
4147 break;
4148 //reflected magic needs to happen in mirrors:
4149 //
4150 //findentrance(bx,by,mfREFMAGIC,true)
4151 case wRefFireball:
4152 findentrance(bx,by,mfREFFIREBALL,true);
4153 break;
4154 case wBomb:
4155 findentrance(bx+w->txsz,by+tysz+(isSideViewGravity()?2:-3),mfBOMB,true);
4156 break;
4157
4158 case wSBomb:
4159 findentrance(bx+w->txsz,by+tysz+(isSideViewGravity()?2:-3),mfSBOMB,true);
4160 break;
4161
4162 case wFire:
4163 findentrance(bx,by,mfBCANDLE,true);
4164 findentrance(bx,by,mfRCANDLE,true);
4165 findentrance(bx,by,mfWANDFIRE,true);
4166 /* if we want the weapon to die
4167 if (findentrance(bx,by,mfBCANDLE,true) ) dead = 1;
4168 if (findentrance(bx,by,mfRCANDLE,true) ) dead = 1;
4169 if (findentrance(bx,by,mfWANDFIRE,true)) dead = 1;
4170 */
4171 break;
4172
4173 case wScript1:
4174 break;
4175 case wScript2:
4176 break;
4177 case wScript3:
4178 break;
4179 case wScript4:
4180 break;
4181 case wScript5:
4182 break;
4183 case wScript6:
4184 break;
4185 case wScript7:
4186 break;
4187 case wScript8:
4188 break;
4189 case wScript9:
4190 break;
4191 case wScript10:
4192 break;
4193 case wIce:
4194 break;
4195 case wCByrna:
4196 break;
4197 case wWhistle:
4198 break;
4199 case wSSparkle:
4200 case wFSparkle:
4201 break;
4202 case wWind:
4203 break;
4204 case wBait:
4205 break;
4206 case wFlame:
4207 case wThrown:
4208 case wBombos:
4209 case wEther:
4210 case wQuake:
4211 case wSwordLA:
4212 case wSword180:
4213 case wStomp:
4214 break;
4215 case wSword:
4216 case wWand:
4217 //case wCandle:
4218 case wHSHandle:
4219 case wLitBomb:
4220 case wLitSBomb:
4221 break;
4222 3072 default: break;
4223
4224 }
4225 3072 }
4226
4227 6144 void HeroClass::check_slash_block_layer2(int32_t bx, int32_t by, weapon *w, int32_t layer)
4228 {
4229
4230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6144 times.
6144 if(!(get_bit(quest_rules,qr_BUSHESONLAYERS1AND2)))
4231 {
4232 //zprint("bit off\n");
4233 6144 return;
4234 }
4235 //keep things inside the screen boundaries
4236 bx=vbound(bx, 0, 255);
4237 by=vbound(by, 0, 176);
4238 int32_t fx=vbound(bx, 0, 255);
4239 int32_t fy=vbound(by, 0, 176);
4240 //first things first
4241 if(w->useweapon != wSword)
4242 return;
4243
4244 //find out which combo row/column the coordinates are in
4245 bx &= 0xF0;
4246 by &= 0xF0;
4247
4248
4249 int32_t flag = MAPFLAGL(layer,bx,by);
4250 int32_t flag2 = MAPCOMBOFLAGL(layer,bx,by);
4251 int32_t cid = MAPCOMBOL(layer,bx,by);
4252 int32_t type = combobuf[cid].type;
4253 if(combobuf[cid].triggerflags[0] & combotriggerONLYGENTRIG)
4254 type = cNONE;
4255 //zprint("cid is: %d\n", cid);
4256 //zprint("type is: %d\n", type);
4257 int32_t i = (bx>>4) + by;
4258
4259 if(i > 175)
4260 return;
4261
4262 if((get_bit(w->wscreengrid_layer[layer-1], i) != 0) || (!isCuttableType(type)))
4263 {
4264 return;
4265 //ignorescreen = true;
4266 //zprint("ignoring\n");
4267 }
4268
4269 int32_t sworditem = (directWpn>-1 && itemsbuf[directWpn].family==itype_sword) ? itemsbuf[directWpn].fam_type : current_item(itype_sword);
4270
4271 {
4272 if(!isTouchyType(type) && !get_bit(quest_rules, qr_CONT_SWORD_TRIGGERS)) set_bit(w->wscreengrid_layer[layer-1],i,1);
4273 if(isCuttableNextType(type) || isCuttableNextType(type))
4274 {
4275 FFCore.tempScreens[layer]->data[i]++;
4276 }
4277 else
4278 {
4279 FFCore.tempScreens[layer]->data[i] = tmpscr->undercombo;
4280 FFCore.tempScreens[layer]->cset[i] = tmpscr->undercset;
4281 FFCore.tempScreens[layer]->sflag[i] = 0;
4282 }
4283 if((flag==mfARMOS_ITEM||flag2==mfARMOS_ITEM) && (!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN)))
4284 {
4285 items.add(new item((zfix)bx, (zfix)by,(zfix)0, tmpscr->catchall, ipONETIME2 + ipBIGRANGE + ipHOLDUP | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0), 0));
4286 sfx(tmpscr->secretsfx);
4287 }
4288 else if(isCuttableItemType(type))
4289 {
4290 int32_t it = -1;
4291 int32_t thedropset = -1;
4292
4293 if ( (combobuf[cid].usrflags&cflag2) )
4294 {
4295 if(combobuf[cid].usrflags&cflag11)
4296 it = combobuf[cid].attribytes[1];
4297 else
4298 {
4299 it = select_dropitem(combobuf[cid].attribytes[1]);
4300 thedropset = combobuf[cid].attribytes[1];
4301 }
4302 }
4303 else
4304 {
4305 it = select_dropitem(12);
4306 thedropset = 12;
4307 }
4308
4309 if(it!=-1)
4310 {
4311 item* itm = (new item((zfix)bx, (zfix)by,(zfix)0, it, ipBIGRANGE + ipTIMER, 0));
4312 itm->from_dropset = thedropset;
4313 items.add(itm);
4314 }
4315 }
4316
4317 putcombo(scrollbuf,(i&15)<<4,i&0xF0,tmpscr->data[i],tmpscr->cset[i]);
4318
4319 if(get_bit(quest_rules,qr_MORESOUNDS))
4320 {
4321 if (!isBushType(type) && !isFlowersType(type) && !isGrassType(type))
4322 {
4323 if (combobuf[cid].usrflags&cflag3)
4324 {
4325 sfx(combobuf[cid].attribytes[2],int32_t(bx));
4326 }
4327 }
4328 else
4329 {
4330 if (combobuf[cid].usrflags&cflag3)
4331 {
4332 sfx(combobuf[cid].attribytes[2],int32_t(bx));
4333 }
4334 else sfx(QMisc.miscsfx[sfxBUSHGRASS],int32_t(bx));
4335 }
4336 }
4337
4338 int16_t decotype = (combobuf[cid].usrflags & cflag1) ? ((combobuf[cid].usrflags & cflag10) ? (combobuf[cid].attribytes[0]) : (-1)) : (0);
4339 if(decotype > 3) decotype = 0;
4340 if(!decotype) decotype = (isBushType(type) ? 1 : (isFlowersType(type) ? 2 : (isGrassType(type) ? 3 : ((combobuf[cid].usrflags & cflag1) ? -1 : -2))));
4341 switch(decotype)
4342 {
4343 case -2: break; //nothing
4344 case -1:
4345 decorations.add(new comboSprite((zfix)fx, (zfix)fy, 0, 0, combobuf[cid].attribytes[0]));
4346 break;
4347 case 1: decorations.add(new dBushLeaves((zfix)fx, (zfix)fy, dBUSHLEAVES, 0, 0)); break;
4348 case 2: decorations.add(new dFlowerClippings((zfix)fx, (zfix)fy, dFLOWERCLIPPINGS, 0, 0)); break;
4349 case 3: decorations.add(new dGrassClippings((zfix)fx, (zfix)fy, dGRASSCLIPPINGS, 0, 0)); break;
4350 }
4351
4352 }
4353
4354 6144 }
4355
4356 3072 void HeroClass::check_slash_block2(int32_t bx, int32_t by, weapon *w)
4357 {
4358 /*
4359 int32_t par_item = w->parentitem;
4360 al_trace("check_slash_block(weapon *w): par_item is: %d\n", par_item);
4361 int32_t usewpn = -1;
4362 if ( par_item > -1 )
4363 {
4364 usewpn = itemsbuf[par_item].useweapon;
4365 }
4366 else if ( par_item == -1 && w->ScriptGenerated )
4367 {
4368 usewpn = w->useweapon;
4369 }
4370 al_trace("check_slash_block(weapon *w): usewpn is: %d\n", usewpn);
4371 */
4372
4373
4374 //keep things inside the screen boundaries
4375 3072 bx=vbound(bx, 0, 255);
4376 3072 by=vbound(by, 0, 176);
4377 3072 int32_t fx=vbound(bx, 0, 255);
4378 3072 int32_t fy=vbound(by, 0, 176);
4379 3072 int32_t cid = MAPCOMBO(bx,by);
4380
4381 //find out which combo row/column the coordinates are in
4382 3072 bx &= 0xF0;
4383 3072 by &= 0xF0;
4384
4385 3072 int32_t type = COMBOTYPE(bx,by);
4386 3072 int32_t type2 = FFCOMBOTYPE(fx,fy);
4387 3072 int32_t flag = MAPFLAG(bx,by);
4388 3072 int32_t flag2 = MAPCOMBOFLAG(bx,by);
4389 3072 int32_t flag3 = MAPFFCOMBOFLAG(fx,fy);
4390
1/2
✓ Branch 0 taken 3072 times.
✗ Branch 1 not taken.
3072 if(combobuf[cid].triggerflags[0] & combotriggerONLYGENTRIG)
4391 type = cNONE;
4392 3072 byte dontignore = 0;
4393 3072 byte dontignoreffc = 0;
4394
4395
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3072 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3072 if (isCuttableType(type) && MatchComboTrigger(w, combobuf, cid))
4396 {
4397 al_trace("This weapon (%d) can slash the combo: combobuf[%d].\n", w->id, cid);
4398 dontignore = 1;
4399 }
4400
4401 /*to-do, ffcs
4402 if (isCuttableType(type2) && MatchComboTrigger(w, combobuf, cid))
4403 {
4404 al_trace("This weapon (%d) can slash the combo: combobuf[%d].\n", w->id, cid);
4405 dontignoreffc = 1;
4406 }*/
4407
2/4
✓ Branch 0 taken 3072 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3072 times.
✗ Branch 3 not taken.
3072 if(w->useweapon != wSword && !dontignore) return;
4408
4409
4410 int32_t i = (bx>>4) + by;
4411 if (get_bit(w->wscreengrid,(((bx>>4) + by))) ) return;
4412
4413 if(i > 175)
4414 return;
4415
4416 bool ignorescreen=false;
4417 bool ignoreffc=false;
4418
4419 if(get_bit(w->wscreengrid, i) != 0)
4420 {
4421 ignorescreen = true; dontignore = 0;
4422 }
4423
4424 int32_t current_ffcombo = getFFCAt(fx,fy);
4425
4426 if(current_ffcombo == -1 || get_bit(ffcgrid, current_ffcombo) != 0)
4427 {
4428 ignoreffc = true;
4429 }
4430 else if(combobuf[tmpscr->ffcs[current_ffcombo].getData()].triggerflags[0] & combotriggerONLYGENTRIG)
4431 type2 = cNONE;
4432 if(!isCuttableType(type) &&
4433 (flag<mfSWORD || flag>mfXSWORD) && flag!=mfSTRIKE && (flag2<mfSWORD || flag2>mfXSWORD) && flag2!=mfSTRIKE)
4434 {
4435 ignorescreen = true;
4436 }
4437
4438 if(!isCuttableType(type2) &&
4439 (flag3<mfSWORD || flag3>mfXSWORD) && flag3!=mfSTRIKE)
4440 {
4441 ignoreffc = true;
4442 }
4443
4444 mapscr *s = tmpscr + ((currscr>=128) ? 1 : 0);
4445
4446 int32_t sworditem = (directWpn>-1 && itemsbuf[directWpn].family==itype_sword) ? itemsbuf[directWpn].fam_type : current_item(itype_sword);
4447 byte skipsecrets = 0;
4448 if ( isNextType(type) ) //->Next combos should not trigger secrets. Their child combo, may want to do that! -Z 17th December, 2019
4449 {
4450 if (get_bit(quest_rules,qr_OLD_SLASHNEXT_SECRETS))
4451 {
4452 skipsecrets = 0;
4453 }
4454 else skipsecrets = 1;
4455 }
4456 if((!skipsecrets || !get_bit(quest_rules,qr_BUGGY_BUGGY_SLASH_TRIGGERS)) && (!ignorescreen || dontignore))
4457 {
4458 if((flag >= 16)&&(flag <= 31)&&!skipsecrets)
4459 {
4460 s->data[i] = s->secretcombo[(s->sflag[i])-16+4];
4461 s->cset[i] = s->secretcset[(s->sflag[i])-16+4];
4462 s->sflag[i] = s->secretflag[(s->sflag[i])-16+4];
4463 }
4464 else if(flag == mfARMOS_SECRET)
4465 {
4466 s->data[i] = s->secretcombo[sSTAIRS];
4467 s->cset[i] = s->secretcset[sSTAIRS];
4468 s->sflag[i] = s->secretflag[sSTAIRS];
4469 sfx(tmpscr->secretsfx);
4470 }
4471 else if(((flag>=mfSWORD&&flag<=mfXSWORD)||(flag==mfSTRIKE)))
4472 {
4473 for(int32_t i2=0; i2<=zc_min(sworditem-1,3); i2++)
4474 {
4475 findentrance(bx,by,mfSWORD+i2,true);
4476 }
4477
4478 findentrance(bx,by,mfSTRIKE,true);
4479 }
4480 else if(((flag2 >= 16)&&(flag2 <= 31)))
4481 {
4482 s->data[i] = s->secretcombo[(s->sflag[i])-16+4];
4483 s->cset[i] = s->secretcset[(s->sflag[i])-16+4];
4484 s->sflag[i] = s->secretflag[(s->sflag[i])-16+4];
4485 }
4486 else if(flag2 == mfARMOS_SECRET)
4487 {
4488 s->data[i] = s->secretcombo[sSTAIRS];
4489 s->cset[i] = s->secretcset[sSTAIRS];
4490 s->sflag[i] = s->secretflag[sSTAIRS];
4491 sfx(tmpscr->secretsfx);
4492 }
4493 else if(((flag2>=mfSWORD&&flag2<=mfXSWORD)||(flag2==mfSTRIKE)))
4494 {
4495 for(int32_t i2=0; i2<=zc_min(sworditem-1,3); i2++)
4496 {
4497 findentrance(bx,by,mfSWORD+i2,true);
4498 }
4499
4500 findentrance(bx,by,mfSTRIKE,true);
4501 }
4502 else
4503 {
4504 if(isCuttableNextType(type))
4505 {
4506 s->data[i]++;
4507 }
4508 else
4509 {
4510 s->data[i] = s->undercombo;
4511 s->cset[i] = s->undercset;
4512 s->sflag[i] = 0;
4513 }
4514
4515 //pausenow=true;
4516 }
4517 }
4518 else if(skipsecrets && (!ignorescreen || dontignore))
4519 {
4520 if(isCuttableNextType(type))
4521 {
4522 s->data[i]++;
4523 }
4524 else
4525 {
4526 s->data[i] = s->undercombo;
4527 s->cset[i] = s->undercset;
4528 s->sflag[i] = 0;
4529 }
4530 }
4531
4532 if(((flag3>=mfSWORD&&flag3<=mfXSWORD)||(flag3==mfSTRIKE)) && !ignoreffc)
4533 {
4534 for(int32_t i2=0; i2<=zc_min(sworditem-1,3); i2++)
4535 {
4536 findentrance(bx,by,mfSWORD+i2,true);
4537 }
4538
4539 findentrance(fx,fy,mfSTRIKE,true);
4540 }
4541 else if(!ignoreffc)
4542 {
4543 if(isCuttableNextType(type2))
4544 {
4545 s->ffcs[current_ffcombo].incData(1);
4546 }
4547 else
4548 {
4549 s->ffcs[current_ffcombo].setData(s->undercombo);
4550 s->ffcs[current_ffcombo].cset = s->undercset;
4551 }
4552 }
4553
4554 if(!ignorescreen || dontignore)
4555 {
4556 if(!isTouchyType(type) && !get_bit(quest_rules, qr_CONT_SWORD_TRIGGERS)) set_bit(w->wscreengrid,i,1);
4557
4558 if((flag==mfARMOS_ITEM||flag2==mfARMOS_ITEM) && (!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN)))
4559 {
4560 items.add(new item((zfix)bx, (zfix)by,(zfix)0, tmpscr->catchall, ipONETIME2 + ipBIGRANGE + ipHOLDUP | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0), 0));
4561 sfx(tmpscr->secretsfx);
4562 }
4563 else if(isCuttableItemType(type))
4564 {
4565 int32_t it = -1;
4566 int32_t thedropset = -1;
4567 if ( (combobuf[cid].usrflags&cflag2) ) //specific dropset or item
4568 {
4569 if ( combobuf[cid].usrflags&cflag11 )
4570 {
4571 it = combobuf[cid].attribytes[1];
4572 }
4573 else
4574 {
4575 it = select_dropitem(combobuf[cid].attribytes[1]);
4576 thedropset = combobuf[cid].attribytes[1];
4577 }
4578 }
4579 else
4580 {
4581 it = select_dropitem(12);
4582 thedropset = 12;
4583 }
4584
4585 if(it!=-1)
4586 {
4587 item* itm = (new item((zfix)bx, (zfix)by,(zfix)0, it, ipBIGRANGE + ipTIMER, 0));
4588 itm->from_dropset = thedropset;
4589 items.add(itm);
4590 }
4591 }
4592
4593
4594 putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]);
4595
4596 if(get_bit(quest_rules,qr_MORESOUNDS))
4597 {
4598 if (!isBushType(type) && !isFlowersType(type) && !isGrassType(type))
4599 {
4600 if (combobuf[cid].usrflags&cflag3)
4601 {
4602 sfx(combobuf[cid].attribytes[2],int32_t(bx));
4603 }
4604 }
4605 else
4606 {
4607 if (combobuf[cid].usrflags&cflag3)
4608 {
4609 sfx(combobuf[cid].attribytes[2],int32_t(bx));
4610 }
4611 else sfx(QMisc.miscsfx[sfxBUSHGRASS],int32_t(bx));
4612 }
4613 }
4614
4615 int16_t decotype = (combobuf[cid].usrflags & cflag1) ? ((combobuf[cid].usrflags & cflag10) ? (combobuf[cid].attribytes[0]) : (-1)) : (0);
4616 if(decotype > 3) decotype = 0;
4617 if(!decotype) decotype = (isBushType(type) ? 1 : (isFlowersType(type) ? 2 : (isGrassType(type) ? 3 : ((combobuf[cid].usrflags & cflag1) ? -1 : -2))));
4618 switch(decotype)
4619 {
4620 case -2: break; //nothing
4621 case -1:
4622 decorations.add(new comboSprite((zfix)fx, (zfix)fy, 0, 0, combobuf[cid].attribytes[0]));
4623 break;
4624 case 1: decorations.add(new dBushLeaves((zfix)fx, (zfix)fy, dBUSHLEAVES, 0, 0)); break;
4625 case 2: decorations.add(new dFlowerClippings((zfix)fx, (zfix)fy, dFLOWERCLIPPINGS, 0, 0)); break;
4626 case 3: decorations.add(new dGrassClippings((zfix)fx, (zfix)fy, dGRASSCLIPPINGS, 0, 0)); break;
4627 }
4628 }
4629
4630 if(!ignoreffc)
4631 {
4632 if(!isTouchyType(type2) && !get_bit(quest_rules, qr_CONT_SWORD_TRIGGERS)) set_bit(ffcgrid, current_ffcombo, 1);
4633
4634 if(isCuttableItemType(type2))
4635 {
4636 int32_t it=-1;
4637 int32_t thedropset=-1;
4638 if ( (combobuf[cid].usrflags&cflag2) )
4639 {
4640 if(combobuf[cid].usrflags&cflag11)
4641 it = combobuf[cid].attribytes[1];
4642 else
4643 {
4644 it = select_dropitem(combobuf[cid].attribytes[1]);
4645 thedropset = combobuf[cid].attribytes[1];
4646 }
4647 }
4648 else
4649 {
4650 int32_t r=zc_oldrand()%100;
4651
4652 if(r<15)
4653 {
4654 it=iHeart; // 15%
4655 }
4656 else if(r<35)
4657 {
4658 it=iRupy; // 20%
4659 }
4660 }
4661
4662 if(it!=-1 && itemsbuf[it].family != itype_misc) // Don't drop non-gameplay items
4663 {
4664 item* itm = (new item((zfix)fx, (zfix)fy,(zfix)0, it, ipBIGRANGE + ipTIMER, 0));
4665 itm->from_dropset = thedropset;
4666 items.add(itm);
4667 }
4668 }
4669
4670 if(get_bit(quest_rules,qr_MORESOUNDS))
4671 {
4672 if (!isBushType(type2) && !isFlowersType(type2) && !isGrassType(type2))
4673 {
4674 if (combobuf[cid].usrflags&cflag3)
4675 {
4676 sfx(combobuf[cid].attribytes[2],int32_t(bx));
4677 }
4678 }
4679 else
4680 {
4681 if (combobuf[cid].usrflags&cflag3)
4682 {
4683 sfx(combobuf[cid].attribytes[2],int32_t(bx));
4684 }
4685 else sfx(QMisc.miscsfx[sfxBUSHGRASS],int32_t(bx));
4686 }
4687 }
4688
4689 int16_t decotype = (combobuf[cid].usrflags & cflag1) ? ((combobuf[cid].usrflags & cflag10) ? (combobuf[cid].attribytes[0]) : (-1)) : (0);
4690 if(decotype > 3) decotype = 0;
4691 if(!decotype) decotype = (isBushType(type2) ? 1 : (isFlowersType(type2) ? 2 : (isGrassType(type2) ? 3 : ((combobuf[cid].usrflags & cflag1) ? -1 : -2))));
4692 switch(decotype)
4693 {
4694 case -2: break; //nothing
4695 case -1:
4696 decorations.add(new comboSprite((zfix)fx, (zfix)fy, 0, 0, combobuf[cid].attribytes[0]));
4697 break;
4698 case 1: decorations.add(new dBushLeaves((zfix)fx, (zfix)fy, dBUSHLEAVES, 0, 0)); break;
4699 case 2: decorations.add(new dFlowerClippings((zfix)fx, (zfix)fy, dFLOWERCLIPPINGS, 0, 0)); break;
4700 case 3: decorations.add(new dGrassClippings((zfix)fx, (zfix)fy, dGRASSCLIPPINGS, 0, 0)); break;
4701 }
4702 }
4703 3072 }
4704
4705 3072 void HeroClass::check_wand_block2(int32_t bx, int32_t by, weapon *w)
4706 {
4707 /*
4708 int32_t par_item = w->parentitem;
4709 al_trace("check_wand_block(weapon *w): par_item is: %d\n", par_item);
4710 int32_t usewpn = -1;
4711 if ( par_item > -1 )
4712 {
4713 usewpn = itemsbuf[par_item].useweapon;
4714 }
4715 else if ( par_item == -1 && w->ScriptGenerated )
4716 {
4717 usewpn = w->useweapon;
4718 }
4719 al_trace("check_wand_block(weapon *w): usewpn is: %d\n", usewpn);
4720 */
4721
4722 3072 byte dontignore = 0;
4723 3072 byte dontignoreffc = 0;
4724
4725
4726
4727
4728
4729 //keep things inside the screen boundaries
4730 3072 bx=vbound(bx, 0, 255);
4731 3072 by=vbound(by, 0, 176);
4732 3072 int32_t fx=vbound(bx, 0, 255);
4733 3072 int32_t fy=vbound(by, 0, 176);
4734 3072 int32_t cid = MAPCOMBO(bx,by);
4735
4736 //Z_scripterrlog("check_wand_block2 MatchComboTrigger() returned: %d\n", );
4737
2/4
✓ Branch 0 taken 3072 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3072 times.
3072 if(w->useweapon != wWand && !MatchComboTrigger (w, combobuf, cid)) return;
4738 if ( MatchComboTrigger (w, combobuf, cid) ) dontignore = 1;
4739
4740 //first things first
4741 if(z>8||fakez>8) return;
4742
4743 //find out which combo row/column the coordinates are in
4744 bx &= 0xF0;
4745 by &= 0xF0;
4746
4747 int32_t flag = MAPFLAG(bx,by);
4748 int32_t flag2 = MAPCOMBOFLAG(bx,by);
4749 int32_t flag3=0;
4750 int32_t flag31 = MAPFFCOMBOFLAG(fx,fy);
4751 int32_t flag32 = MAPFFCOMBOFLAG(fx,fy);
4752 int32_t flag33 = MAPFFCOMBOFLAG(fx,fy);
4753 int32_t flag34 = MAPFFCOMBOFLAG(fx,fy);
4754
4755 if(flag31==mfWAND||flag32==mfWAND||flag33==mfWAND||flag34==mfWAND)
4756 flag3=mfWAND;
4757
4758 if(flag31==mfSTRIKE||flag32==mfSTRIKE||flag33==mfSTRIKE||flag34==mfSTRIKE)
4759 flag3=mfSTRIKE;
4760
4761 int32_t i = (bx>>4) + by;
4762
4763 if(flag!=mfWAND&&flag2!=mfWAND&&flag3!=mfWAND&&flag!=mfSTRIKE&&flag2!=mfSTRIKE&&flag3!=mfSTRIKE)
4764 return;
4765
4766 if(i > 175)
4767 return;
4768
4769 //mapscr *s = tmpscr + ((currscr>=128) ? 1 : 0);
4770
4771 //findentrance(bx,by,mfWAND,true);
4772 //findentrance(bx,by,mfSTRIKE,true);
4773 if((findentrance(bx,by,mfWAND,true)==false)&&(findentrance(bx,by,mfSTRIKE,true)==false))
4774 {
4775 if(flag3==mfWAND||flag3==mfSTRIKE)
4776 {
4777 findentrance(fx,fy,mfWAND,true);
4778 findentrance(fx,fy,mfSTRIKE,true);
4779 }
4780 }
4781
4782 if(dontignore) { findentrance(bx,by,mfWAND,true); }
4783
4784 //putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]);
4785 3072 }
4786
4787 3072 void HeroClass::check_pound_block2(int32_t bx, int32_t by, weapon *w)
4788 {
4789 /*
4790 int32_t par_item = w->parentitem;
4791 al_trace("check_pound_block(weapon *w): par_item is: %d\n", par_item);
4792 int32_t usewpn = -1;
4793 if ( par_item > -1 )
4794 {
4795 usewpn = itemsbuf[par_item].useweapon;
4796 }
4797 else if ( par_item == -1 && w->ScriptGenerated )
4798 {
4799 usewpn = w->useweapon;
4800 }
4801 al_trace("check_pound_block(weapon *w): usewpn is: %d\n", usewpn);
4802 */
4803 //keep things inside the screen boundaries
4804 3072 bx=vbound(bx, 0, 255);
4805 3072 by=vbound(by, 0, 176);
4806 3072 int32_t fx=vbound(bx, 0, 255);
4807 3072 int32_t fy=vbound(by, 0, 176);
4808 3072 int32_t cid = MAPCOMBO(bx,by);
4809 3072 byte dontignore = MatchComboTrigger (w, combobuf, cid);
4810
2/4
✓ Branch 0 taken 3072 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3072 times.
3072 if(w->useweapon != wHammer && !dontignore ) return;
4811
4812
4813
4814
4815 //first things first
4816 if(z>8||fakez>8) return;
4817
4818 //find out which combo row/column the coordinates are in
4819 bx &= 0xF0;
4820 by &= 0xF0;
4821
4822 int32_t type = COMBOTYPE(bx,by);
4823 int32_t type2 = FFCOMBOTYPE(fx,fy);
4824 int32_t flag = MAPFLAG(bx,by);
4825 int32_t flag2 = MAPCOMBOFLAG(bx,by);
4826 int32_t flag3 = MAPFFCOMBOFLAG(fx,fy);
4827 int32_t i = (bx>>4) + by;
4828 if (get_bit(w->wscreengrid,(((bx>>4) + by))) ) return;
4829
4830 if(i > 175)
4831 return;
4832
4833 bool ignorescreen=false;
4834 bool ignoreffc=false;
4835 bool pound=false;
4836
4837 if(combobuf[cid].triggerflags[0] & combotriggerONLYGENTRIG)
4838 type = cNONE;
4839 if(type!=cPOUND && flag!=mfHAMMER && flag!=mfSTRIKE && flag2!=mfHAMMER && flag2!=mfSTRIKE)
4840 ignorescreen = true; // Affect only FFCs
4841
4842 if(get_bit(w->wscreengrid, i) != 0)
4843 {
4844 ignorescreen = true; dontignore = 0;
4845 }
4846
4847 int32_t current_ffcombo = getFFCAt(fx,fy);
4848
4849 if(current_ffcombo == -1 || get_bit(ffcgrid, current_ffcombo) != 0)
4850 ignoreffc = true;
4851 else if(combobuf[tmpscr->ffcs[current_ffcombo].getData()].triggerflags[0] & combotriggerONLYGENTRIG)
4852 type2 = cNONE;
4853 if(type2!=cPOUND && flag3!=mfSTRIKE && flag3!=mfHAMMER)
4854 ignoreffc = true;
4855
4856 if(ignorescreen && ignoreffc) // Nothing to do.
4857 return;
4858
4859 mapscr *s = tmpscr + ((currscr>=128) ? 1 : 0);
4860
4861 if(!ignorescreen || dontignore)
4862 {
4863 if(flag==mfHAMMER||flag==mfSTRIKE) // Takes precedence over Secret Tile and Armos->Secret
4864 {
4865 findentrance(bx,by,mfHAMMER,true);
4866 findentrance(bx,by,mfSTRIKE,true);
4867 }
4868 else if(flag2==mfHAMMER||flag2==mfSTRIKE)
4869 {
4870 findentrance(bx,by,mfHAMMER,true);
4871 findentrance(bx,by,mfSTRIKE,true);
4872 }
4873 else if((flag >= 16)&&(flag <= 31))
4874 {
4875 s->data[i] = s->secretcombo[(s->sflag[i])-16+4];
4876 s->cset[i] = s->secretcset[(s->sflag[i])-16+4];
4877 s->sflag[i] = s->secretflag[(s->sflag[i])-16+4];
4878 }
4879 else if(flag == mfARMOS_SECRET)
4880 {
4881 s->data[i] = s->secretcombo[sSTAIRS];
4882 s->cset[i] = s->secretcset[sSTAIRS];
4883 s->sflag[i] = s->secretflag[sSTAIRS];
4884 sfx(tmpscr->secretsfx);
4885 }
4886 else if((flag2 >= 16)&&(flag2 <= 31))
4887 {
4888 s->data[i] = s->secretcombo[(s->sflag[i])-16+4];
4889 s->cset[i] = s->secretcset[(s->sflag[i])-16+4];
4890 s->sflag[i] = s->secretflag[(s->sflag[i])-16+4];
4891 }
4892 else if(flag2 == mfARMOS_SECRET)
4893 {
4894 s->data[i] = s->secretcombo[sSTAIRS];
4895 s->cset[i] = s->secretcset[sSTAIRS];
4896 s->sflag[i] = s->secretflag[sSTAIRS];
4897 sfx(tmpscr->secretsfx);
4898 }
4899 else pound = true;
4900 }
4901
4902 if(!ignoreffc)
4903 {
4904 if(flag3==mfHAMMER||flag3==mfSTRIKE)
4905 {
4906 findentrance(fx,fy,mfHAMMER,true);
4907 findentrance(fx,fy,mfSTRIKE,true);
4908 }
4909 else
4910 {
4911 s->ffcs[current_ffcombo].incData(1);
4912 }
4913 }
4914
4915 if(!ignorescreen || dontignore)
4916 {
4917 if(pound)
4918 s->data[i]+=1;
4919
4920 set_bit(w->wscreengrid,i,1);
4921
4922 if((flag==mfARMOS_ITEM||flag2==mfARMOS_ITEM) && (!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN)))
4923 {
4924 items.add(new item((zfix)bx, (zfix)by, (zfix)0, tmpscr->catchall, ipONETIME2 + ipBIGRANGE + ipHOLDUP | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0), 0));
4925 sfx(tmpscr->secretsfx);
4926 }
4927
4928 if(type==cPOUND && get_bit(quest_rules,qr_MORESOUNDS))
4929 sfx(QMisc.miscsfx[sfxHAMMERPOUND],int32_t(bx));
4930
4931 putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]);
4932 }
4933
4934 if(!ignoreffc)
4935 {
4936 set_bit(ffcgrid,current_ffcombo,1);
4937
4938 if(type2==cPOUND && get_bit(quest_rules,qr_MORESOUNDS))
4939 sfx(QMisc.miscsfx[sfxHAMMERPOUND],int32_t(bx));
4940 }
4941
4942 return;
4943 3072 }
4944
4945 void HeroClass::check_slash_block(weapon *w)
4946 {
4947 //first things
4948
4949 int32_t par_item = w->parentitem;
4950 al_trace("check_slash_block(weapon *w): par_item is: %d\n", par_item);
4951 int32_t usewpn = -1;
4952 if ( par_item > -1 )
4953 {
4954 usewpn = itemsbuf[par_item].useweapon;
4955 }
4956 else if ( par_item == -1 && w->ScriptGenerated )
4957 {
4958 usewpn = w->useweapon;
4959 }
4960 al_trace("check_slash_block(weapon *w): usewpn is: %d\n", usewpn);
4961 if(usewpn != wSword) return;
4962
4963
4964 int32_t bx = 0, by = 0;
4965 bx = ((int32_t)w->x) + (((int32_t)w->hxsz)/2);
4966 by = ((int32_t)w->y) + (((int32_t)w->hysz)/2);
4967 al_trace("check_slash_block(weapon *w): bx is: %d\n", bx);
4968 al_trace("check_slash_block(weapon *w): by is: %d\n", by);
4969 //keep things inside the screen boundaries
4970 bx=vbound(bx, 0, 255);
4971 by=vbound(by, 0, 176);
4972 int32_t fx=vbound(bx, 0, 255);
4973 int32_t fy=vbound(by, 0, 176);
4974
4975 int32_t cid = MAPCOMBO(bx,by);
4976
4977 //find out which combo row/column the coordinates are in
4978 bx &= 0xF0;
4979 by &= 0xF0;
4980
4981 int32_t type = COMBOTYPE(bx,by);
4982 int32_t type2 = FFCOMBOTYPE(fx,fy);
4983 int32_t flag = MAPFLAG(bx,by);
4984 int32_t flag2 = MAPCOMBOFLAG(bx,by);
4985 int32_t flag3 = MAPFFCOMBOFLAG(fx,fy);
4986 int32_t i = (bx>>4) + by;
4987
4988 if(i > 175)
4989 {
4990 al_trace("check_slash_block(weapon *w): %s\n", "i > 175");
4991 return;
4992 }
4993
4994 if(combobuf[cid].triggerflags[0] & combotriggerONLYGENTRIG)
4995 type = cNONE;
4996 bool ignorescreen=false;
4997 bool ignoreffc=false;
4998
4999 if(get_bit(screengrid, i) != 0)
5000 {
5001 ignorescreen = true;
5002 }
5003
5004 int32_t current_ffcombo = getFFCAt(fx,fy);
5005
5006 if(current_ffcombo == -1 || get_bit(ffcgrid, current_ffcombo) != 0)
5007 {
5008 ignoreffc = true;
5009 }
5010 else if(combobuf[tmpscr->ffcs[current_ffcombo].getData()].triggerflags[0] & combotriggerONLYGENTRIG)
5011 type2 = cNONE;
5012 if(!isCuttableType(type) &&
5013 (flag<mfSWORD || flag>mfXSWORD) && flag!=mfSTRIKE && (flag2<mfSWORD || flag2>mfXSWORD) && flag2!=mfSTRIKE)
5014 {
5015 ignorescreen = true;
5016 }
5017
5018 if(!isCuttableType(type2) &&
5019 (flag3<mfSWORD || flag3>mfXSWORD) && flag3!=mfSTRIKE)
5020 {
5021 ignoreffc = true;
5022 }
5023
5024 mapscr *s = tmpscr + ((currscr>=128) ? 1 : 0);
5025
5026 int32_t sworditem = (par_item >-1 ? itemsbuf[par_item].fam_type : current_item(itype_sword)); //Get the level of the item, else the highest sword level in inventory.
5027
5028 if(!ignorescreen)
5029 {
5030 if((flag >= 16)&&(flag <= 31))
5031 {
5032 s->data[i] = s->secretcombo[(s->sflag[i])-16+4];
5033 s->cset[i] = s->secretcset[(s->sflag[i])-16+4];
5034 s->sflag[i] = s->secretflag[(s->sflag[i])-16+4];
5035 }
5036 else if(flag == mfARMOS_SECRET)
5037 {
5038 s->data[i] = s->secretcombo[sSTAIRS];
5039 s->cset[i] = s->secretcset[sSTAIRS];
5040 s->sflag[i] = s->secretflag[sSTAIRS];
5041 sfx(tmpscr->secretsfx);
5042 }
5043 else if(((flag>=mfSWORD&&flag<=mfXSWORD)||(flag==mfSTRIKE)))
5044 {
5045 for(int32_t i2=0; i2<=zc_min(sworditem-1,3); i2++)
5046 {
5047 findentrance(bx,by,mfSWORD+i2,true);
5048 }
5049
5050 findentrance(bx,by,mfSTRIKE,true);
5051 }
5052 else if(((flag2 >= 16)&&(flag2 <= 31)))
5053 {
5054 s->data[i] = s->secretcombo[(s->sflag[i])-16+4];
5055 s->cset[i] = s->secretcset[(s->sflag[i])-16+4];
5056 s->sflag[i] = s->secretflag[(s->sflag[i])-16+4];
5057 }
5058 else if(flag2 == mfARMOS_SECRET)
5059 {
5060 s->data[i] = s->secretcombo[sSTAIRS];
5061 s->cset[i] = s->secretcset[sSTAIRS];
5062 s->sflag[i] = s->secretflag[sSTAIRS];
5063 sfx(tmpscr->secretsfx);
5064 }
5065 else if(((flag2>=mfSWORD&&flag2<=mfXSWORD)||(flag2==mfSTRIKE)))
5066 {
5067 for(int32_t i2=0; i2<=zc_min(sworditem-1,3); i2++)
5068 {
5069 findentrance(bx,by,mfSWORD+i2,true);
5070 }
5071
5072 findentrance(bx,by,mfSTRIKE,true);
5073 }
5074 else
5075 {
5076 if(isCuttableNextType(type))
5077 {
5078 s->data[i]++;
5079 }
5080 else
5081 {
5082 s->data[i] = s->undercombo;
5083 s->cset[i] = s->undercset;
5084 s->sflag[i] = 0;
5085 }
5086
5087 //pausenow=true;
5088 }
5089 }
5090
5091 if(((flag3>=mfSWORD&&flag3<=mfXSWORD)||(flag3==mfSTRIKE)) && !ignoreffc)
5092 {
5093 for(int32_t i2=0; i2<=zc_min(sworditem-1,3); i2++)
5094 {
5095 findentrance(bx,by,mfSWORD+i2,true);
5096 }
5097
5098 findentrance(fx,fy,mfSTRIKE,true);
5099 }
5100 else if(!ignoreffc)
5101 {
5102 if(isCuttableNextType(type2))
5103 {
5104 s->ffcs[current_ffcombo].incData(1);
5105 }
5106 else
5107 {
5108 s->ffcs[current_ffcombo].setData(s->undercombo);
5109 s->ffcs[current_ffcombo].cset = s->undercset;
5110 }
5111 }
5112
5113 if(!ignorescreen)
5114 {
5115 if(!isTouchyType(type) && !get_bit(quest_rules, qr_CONT_SWORD_TRIGGERS)) set_bit(screengrid,i,1);
5116
5117 if((flag==mfARMOS_ITEM||flag2==mfARMOS_ITEM) && (!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN)))
5118 {
5119 items.add(new item((zfix)bx, (zfix)by,(zfix)0, tmpscr->catchall, ipONETIME2 + ipBIGRANGE + ipHOLDUP | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0), 0));
5120 sfx(tmpscr->secretsfx);
5121 }
5122 else if(isCuttableItemType(type))
5123 {
5124 int32_t it = -1;
5125 int32_t thedropset = -1;
5126 if ( (combobuf[cid].usrflags&cflag2) ) //specific dropset or item
5127 {
5128 if ( combobuf[cid].usrflags&cflag11 )
5129 {
5130 it = combobuf[cid].attribytes[1];
5131 }
5132 else
5133 {
5134 it = select_dropitem(combobuf[cid].attribytes[1]);
5135 thedropset = combobuf[cid].attribytes[1];
5136 }
5137 }
5138 else
5139 {
5140 it = select_dropitem(12);
5141 thedropset = 12;
5142 }
5143
5144 if(it!=-1)
5145 {
5146 item* itm = (new item((zfix)bx, (zfix)by,(zfix)0, it, ipBIGRANGE + ipTIMER, 0));
5147 itm->from_dropset = thedropset;
5148 items.add(itm);
5149 }
5150 }
5151
5152 putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]);
5153
5154 if(get_bit(quest_rules,qr_MORESOUNDS))
5155 {
5156 if (!isBushType(type) && !isFlowersType(type) && !isGrassType(type))
5157 {
5158 if (combobuf[cid].usrflags&cflag3)
5159 {
5160 sfx(combobuf[cid].attribytes[2],int32_t(bx));
5161 }
5162 }
5163 else
5164 {
5165 if (combobuf[cid].usrflags&cflag3)
5166 {
5167 sfx(combobuf[cid].attribytes[2],int32_t(bx));
5168 }
5169 else sfx(QMisc.miscsfx[sfxBUSHGRASS],int32_t(bx));
5170 }
5171 }
5172
5173 int16_t decotype = (combobuf[cid].usrflags & cflag1) ? ((combobuf[cid].usrflags & cflag10) ? (combobuf[cid].attribytes[0]) : (-1)) : (0);
5174 if(decotype > 3) decotype = 0;
5175 if(!decotype) decotype = (isBushType(type) ? 1 : (isFlowersType(type) ? 2 : (isGrassType(type) ? 3 : ((combobuf[cid].usrflags & cflag1) ? -1 : -2))));
5176 switch(decotype)
5177 {
5178 case -2: break; //nothing
5179 case -1:
5180 decorations.add(new comboSprite((zfix)fx, (zfix)fy, 0, 0, combobuf[cid].attribytes[0]));
5181 break;
5182 case 1: decorations.add(new dBushLeaves((zfix)fx, (zfix)fy, dBUSHLEAVES, 0, 0)); break;
5183 case 2: decorations.add(new dFlowerClippings((zfix)fx, (zfix)fy, dFLOWERCLIPPINGS, 0, 0)); break;
5184 case 3: decorations.add(new dGrassClippings((zfix)fx, (zfix)fy, dGRASSCLIPPINGS, 0, 0)); break;
5185 }
5186 }
5187
5188 if(!ignoreffc)
5189 {
5190 if(!isTouchyType(type2) && !get_bit(quest_rules, qr_CONT_SWORD_TRIGGERS)) set_bit(ffcgrid, current_ffcombo, 1);
5191
5192 if(isCuttableItemType(type2))
5193 {
5194 int32_t it=-1;
5195 int32_t thedropset = -1;
5196 if ( (combobuf[MAPCOMBO(bx,by)-1].usrflags&cflag2) )
5197 {
5198 if(combobuf[MAPCOMBO(bx,by)-1].usrflags&cflag11)
5199 it = combobuf[MAPCOMBO(bx,by)-1].attribytes[1];
5200 else
5201 {
5202 thedropset = combobuf[MAPCOMBO(bx,by)-1].attribytes[1];
5203 it = select_dropitem(thedropset);
5204 }
5205 }
5206 else
5207 {
5208 it = select_dropitem(12);
5209 thedropset = 12;
5210 }
5211
5212 if(it!=-1 && itemsbuf[it].family != itype_misc) // Don't drop non-gameplay items
5213 {
5214 item* itm = (new item((zfix)fx, (zfix)fy,(zfix)0, it, ipBIGRANGE + ipTIMER, 0));
5215 itm->from_dropset = thedropset;
5216 items.add(itm);
5217 }
5218 }
5219
5220 if(get_bit(quest_rules,qr_MORESOUNDS))
5221 {
5222 if (!isBushType(type2) && !isFlowersType(type2) && !isGrassType(type2))
5223 {
5224 if (combobuf[cid].usrflags&cflag3)
5225 {
5226 sfx(combobuf[cid].attribytes[2],int32_t(bx));
5227 }
5228 }
5229 else
5230 {
5231 if (combobuf[cid].usrflags&cflag3)
5232 {
5233 sfx(combobuf[cid].attribytes[2],int32_t(bx));
5234 }
5235 else sfx(QMisc.miscsfx[sfxBUSHGRASS],int32_t(bx));
5236 }
5237 }
5238
5239 int16_t decotype = (combobuf[cid].usrflags & cflag1) ? ((combobuf[cid].usrflags & cflag10) ? (combobuf[cid].attribytes[0]) : (-1)) : (0);
5240 if(decotype > 3) decotype = 0;
5241 if(!decotype) decotype = (isBushType(type2) ? 1 : (isFlowersType(type2) ? 2 : (isGrassType(type2) ? 3 : ((combobuf[cid].usrflags & cflag1) ? -1 : -2))));
5242 switch(decotype)
5243 {
5244 case -2: break; //nothing
5245 case -1:
5246 decorations.add(new comboSprite((zfix)fx, (zfix)fy, 0, 0, combobuf[cid].attribytes[0]));
5247 break;
5248 case 1: decorations.add(new dBushLeaves((zfix)fx, (zfix)fy, dBUSHLEAVES, 0, 0)); break;
5249 case 2: decorations.add(new dFlowerClippings((zfix)fx, (zfix)fy, dFLOWERCLIPPINGS, 0, 0)); break;
5250 case 3: decorations.add(new dGrassClippings((zfix)fx, (zfix)fy, dGRASSCLIPPINGS, 0, 0)); break;
5251 }
5252 }
5253 }
5254
5255 //TODO: Boomerang that cuts bushes. -L
5256 /*void HeroClass::slash_bush()
5257 {
5258
5259 }*/
5260
5261 void HeroClass::check_wand_block(int32_t bx, int32_t by)
5262 {
5263 //keep things inside the screen boundaries
5264 bx=vbound(bx, 0, 255);
5265 by=vbound(by, 0, 176);
5266 int32_t fx=vbound(bx, 0, 255);
5267 int32_t fy=vbound(by, 0, 176);
5268 int32_t cid = MAPCOMBO(bx,by);
5269
5270 //first things first
5271 if(z>8||fakez>8) return;
5272
5273 //find out which combo row/column the coordinates are in
5274 bx &= 0xF0;
5275 by &= 0xF0;
5276
5277 int32_t flag = MAPFLAG(bx,by);
5278 int32_t flag2 = MAPCOMBOFLAG(bx,by);
5279 int32_t flag3=0;
5280 int32_t flag31 = MAPFFCOMBOFLAG(fx,fy);
5281 int32_t flag32 = MAPFFCOMBOFLAG(fx,fy);
5282 int32_t flag33 = MAPFFCOMBOFLAG(fx,fy);
5283 int32_t flag34 = MAPFFCOMBOFLAG(fx,fy);
5284
5285 if(flag31==mfWAND||flag32==mfWAND||flag33==mfWAND||flag34==mfWAND)
5286 flag3=mfWAND;
5287
5288 if(flag31==mfSTRIKE||flag32==mfSTRIKE||flag33==mfSTRIKE||flag34==mfSTRIKE)
5289 flag3=mfSTRIKE;
5290
5291 int32_t i = (bx>>4) + by;
5292
5293 if(flag!=mfWAND&&flag2!=mfWAND&&flag3!=mfWAND&&flag!=mfSTRIKE&&flag2!=mfSTRIKE&&flag3!=mfSTRIKE)
5294 return;
5295
5296 if(i > 175)
5297 return;
5298
5299 //mapscr *s = tmpscr + ((currscr>=128) ? 1 : 0);
5300
5301 //findentrance(bx,by,mfWAND,true);
5302 //findentrance(bx,by,mfSTRIKE,true);
5303 if((findentrance(bx,by,mfWAND,true)==false)&&(findentrance(bx,by,mfSTRIKE,true)==false))
5304 {
5305 if(flag3==mfWAND||flag3==mfSTRIKE)
5306 {
5307 findentrance(fx,fy,mfWAND,true);
5308 findentrance(fx,fy,mfSTRIKE,true);
5309 }
5310 }
5311
5312 //putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]);
5313 }
5314
5315 void HeroClass::check_pound_block(int32_t bx, int32_t by)
5316 {
5317 //keep things inside the screen boundaries
5318 bx=vbound(bx, 0, 255);
5319 by=vbound(by, 0, 176);
5320 int32_t fx=vbound(bx, 0, 255);
5321 int32_t fy=vbound(by, 0, 176);
5322 int32_t cid = MAPCOMBO(bx,by);
5323
5324 //first things first
5325 if(z>8||fakez>8) return;
5326
5327 //find out which combo row/column the coordinates are in
5328 bx &= 0xF0;
5329 by &= 0xF0;
5330
5331 int32_t type = COMBOTYPE(bx,by);
5332 int32_t type2 = FFCOMBOTYPE(fx,fy);
5333 int32_t flag = MAPFLAG(bx,by);
5334 int32_t flag2 = MAPCOMBOFLAG(bx,by);
5335 int32_t flag3 = MAPFFCOMBOFLAG(fx,fy);
5336 int32_t i = (bx>>4) + by;
5337
5338 if(i > 175)
5339 return;
5340
5341 bool ignorescreen=false;
5342 bool ignoreffc=false;
5343 bool pound=false;
5344
5345 if(type!=cPOUND && flag!=mfHAMMER && flag!=mfSTRIKE && flag2!=mfHAMMER && flag2!=mfSTRIKE)
5346 ignorescreen = true; // Affect only FFCs
5347
5348 if(get_bit(screengrid, i) != 0)
5349 ignorescreen = true;
5350
5351 int32_t current_ffcombo = getFFCAt(fx,fy);
5352
5353 if(current_ffcombo == -1 || get_bit(ffcgrid, current_ffcombo) != 0)
5354 ignoreffc = true;
5355
5356 if(type2!=cPOUND && flag3!=mfSTRIKE && flag3!=mfHAMMER)
5357 ignoreffc = true;
5358
5359 if(ignorescreen && ignoreffc) // Nothing to do.
5360 return;
5361
5362 mapscr *s = tmpscr + ((currscr>=128) ? 1 : 0);
5363
5364 if(!ignorescreen)
5365 {
5366 if(flag==mfHAMMER||flag==mfSTRIKE) // Takes precedence over Secret Tile and Armos->Secret
5367 {
5368 findentrance(bx,by,mfHAMMER,true);
5369 findentrance(bx,by,mfSTRIKE,true);
5370 }
5371 else if(flag2==mfHAMMER||flag2==mfSTRIKE)
5372 {
5373 findentrance(bx,by,mfHAMMER,true);
5374 findentrance(bx,by,mfSTRIKE,true);
5375 }
5376 else if((flag >= 16)&&(flag <= 31))
5377 {
5378 s->data[i] = s->secretcombo[(s->sflag[i])-16+4];
5379 s->cset[i] = s->secretcset[(s->sflag[i])-16+4];
5380 s->sflag[i] = s->secretflag[(s->sflag[i])-16+4];
5381 }
5382 else if(flag == mfARMOS_SECRET)
5383 {
5384 s->data[i] = s->secretcombo[sSTAIRS];
5385 s->cset[i] = s->secretcset[sSTAIRS];
5386 s->sflag[i] = s->secretflag[sSTAIRS];
5387 sfx(tmpscr->secretsfx);
5388 }
5389 else if((flag2 >= 16)&&(flag2 <= 31))
5390 {
5391 s->data[i] = s->secretcombo[(s->sflag[i])-16+4];
5392 s->cset[i] = s->secretcset[(s->sflag[i])-16+4];
5393 s->sflag[i] = s->secretflag[(s->sflag[i])-16+4];
5394 }
5395 else if(flag2 == mfARMOS_SECRET)
5396 {
5397 s->data[i] = s->secretcombo[sSTAIRS];
5398 s->cset[i] = s->secretcset[sSTAIRS];
5399 s->sflag[i] = s->secretflag[sSTAIRS];
5400 sfx(tmpscr->secretsfx);
5401 }
5402 else pound = true;
5403 }
5404
5405 if(!ignoreffc)
5406 {
5407 if(flag3==mfHAMMER||flag3==mfSTRIKE)
5408 {
5409 findentrance(fx,fy,mfHAMMER,true);
5410 findentrance(fx,fy,mfSTRIKE,true);
5411 }
5412 else
5413 {
5414 s->ffcs[current_ffcombo].incData(1);
5415 }
5416 }
5417
5418 if(!ignorescreen)
5419 {
5420 if(pound)
5421 s->data[i]+=1;
5422
5423 set_bit(screengrid,i,1);
5424
5425 if((flag==mfARMOS_ITEM||flag2==mfARMOS_ITEM) && (!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN)))
5426 {
5427 items.add(new item((zfix)bx, (zfix)by, (zfix)0, tmpscr->catchall, ipONETIME2 + ipBIGRANGE + ipHOLDUP | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0), 0));
5428 sfx(tmpscr->secretsfx);
5429 }
5430
5431 if(type==cPOUND && get_bit(quest_rules,qr_MORESOUNDS))
5432 sfx(QMisc.miscsfx[sfxHAMMERPOUND],int32_t(bx));
5433
5434 putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]);
5435 }
5436
5437 if(!ignoreffc)
5438 {
5439 set_bit(ffcgrid,current_ffcombo,1);
5440
5441 if(type2==cPOUND && get_bit(quest_rules,qr_MORESOUNDS))
5442 sfx(QMisc.miscsfx[sfxHAMMERPOUND],int32_t(bx));
5443 }
5444
5445 return;
5446 }
5447
5448
5449 void HeroClass::check_wand_block(weapon *w)
5450 {
5451
5452 int32_t par_item = w->parentitem;
5453 al_trace("check_wand_block(weapon *w): par_item is: %d\n", par_item);
5454 int32_t usewpn = -1;
5455 if ( par_item > -1 )
5456 {
5457 usewpn = itemsbuf[par_item].useweapon;
5458 }
5459 else if ( par_item == -1 && w->ScriptGenerated )
5460 {
5461 usewpn = w->useweapon;
5462 }
5463 al_trace("check_wand_block(weapon *w): usewpn is: %d\n", usewpn);
5464 if(usewpn != wWand) return;
5465
5466
5467 int32_t bx = 0, by = 0;
5468 bx = ((int32_t)w->x) + (((int32_t)w->hxsz)/2);
5469 by = ((int32_t)w->y) + (((int32_t)w->hysz)/2);
5470
5471 //keep things inside the screen boundaries
5472 bx=vbound(bx, 0, 255);
5473 by=vbound(by, 0, 176);
5474 int32_t fx=vbound(bx, 0, 255);
5475 int32_t fy=vbound(by, 0, 176);
5476 int32_t cid = MAPCOMBO(bx,by);
5477 //first things first
5478 if(z>8||fakez>8) return;
5479
5480 //find out which combo row/column the coordinates are in
5481 bx &= 0xF0;
5482 by &= 0xF0;
5483
5484 int32_t flag = MAPFLAG(bx,by);
5485 int32_t flag2 = MAPCOMBOFLAG(bx,by);
5486 int32_t flag3=0;
5487 int32_t flag31 = MAPFFCOMBOFLAG(fx,fy);
5488 int32_t flag32 = MAPFFCOMBOFLAG(fx,fy);
5489 int32_t flag33 = MAPFFCOMBOFLAG(fx,fy);
5490 int32_t flag34 = MAPFFCOMBOFLAG(fx,fy);
5491
5492 if(flag31==mfWAND||flag32==mfWAND||flag33==mfWAND||flag34==mfWAND)
5493 flag3=mfWAND;
5494
5495 if(flag31==mfSTRIKE||flag32==mfSTRIKE||flag33==mfSTRIKE||flag34==mfSTRIKE)
5496 flag3=mfSTRIKE;
5497
5498 int32_t i = (bx>>4) + by;
5499
5500 if(flag!=mfWAND&&flag2!=mfWAND&&flag3!=mfWAND&&flag!=mfSTRIKE&&flag2!=mfSTRIKE&&flag3!=mfSTRIKE)
5501 return;
5502
5503 if(i > 175)
5504 return;
5505
5506 //mapscr *s = tmpscr + ((currscr>=128) ? 1 : 0);
5507
5508 //findentrance(bx,by,mfWAND,true);
5509 //findentrance(bx,by,mfSTRIKE,true);
5510 if((findentrance(bx,by,mfWAND,true)==false)&&(findentrance(bx,by,mfSTRIKE,true)==false))
5511 {
5512 if(flag3==mfWAND||flag3==mfSTRIKE)
5513 {
5514 findentrance(fx,fy,mfWAND,true);
5515 findentrance(fx,fy,mfSTRIKE,true);
5516 }
5517 }
5518
5519 //putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]);
5520 }
5521
5522 void HeroClass::check_pound_block(weapon *w)
5523 {
5524
5525 int32_t par_item = w->parentitem;
5526 al_trace("check_pound_block(weapon *w): par_item is: %d\n", par_item);
5527 int32_t usewpn = -1;
5528 if ( par_item > -1 )
5529 {
5530 usewpn = itemsbuf[par_item].useweapon;
5531 }
5532 else if ( par_item == -1 && w->ScriptGenerated )
5533 {
5534 usewpn = w->useweapon;
5535 }
5536 al_trace("check_pound_block(weapon *w): usewpn is: %d\n", usewpn);
5537 if(usewpn != wHammer) return;
5538
5539
5540 int32_t bx = 0, by = 0;
5541 bx = ((int32_t)w->x) + (((int32_t)w->hxsz)/2);
5542 by = ((int32_t)w->y) + (((int32_t)w->hysz)/2);
5543 //keep things inside the screen boundaries
5544 bx=vbound(bx, 0, 255);
5545 by=vbound(by, 0, 176);
5546 int32_t fx=vbound(bx, 0, 255);
5547 int32_t fy=vbound(by, 0, 176);
5548 int32_t cid = MAPCOMBO(bx,by);
5549 //first things first
5550 if(z>8||fakez>8) return;
5551
5552 //find out which combo row/column the coordinates are in
5553 bx &= 0xF0;
5554 by &= 0xF0;
5555
5556 int32_t type = COMBOTYPE(bx,by);
5557 int32_t type2 = FFCOMBOTYPE(fx,fy);
5558 int32_t flag = MAPFLAG(bx,by);
5559 int32_t flag2 = MAPCOMBOFLAG(bx,by);
5560 int32_t flag3 = MAPFFCOMBOFLAG(fx,fy);
5561 int32_t i = (bx>>4) + by;
5562
5563 if(i > 175)
5564 return;
5565
5566 bool ignorescreen=false;
5567 bool ignoreffc=false;
5568 bool pound=false;
5569
5570 if(type!=cPOUND && flag!=mfHAMMER && flag!=mfSTRIKE && flag2!=mfHAMMER && flag2!=mfSTRIKE)
5571 ignorescreen = true; // Affect only FFCs
5572
5573 if(get_bit(screengrid, i) != 0)
5574 ignorescreen = true;
5575
5576 int32_t current_ffcombo = getFFCAt(fx,fy);
5577
5578 if(current_ffcombo == -1 || get_bit(ffcgrid, current_ffcombo) != 0)
5579 ignoreffc = true;
5580
5581 if(type2!=cPOUND && flag3!=mfSTRIKE && flag3!=mfHAMMER)
5582 ignoreffc = true;
5583
5584 if(ignorescreen && ignoreffc) // Nothing to do.
5585 return;
5586
5587 mapscr *s = tmpscr + ((currscr>=128) ? 1 : 0);
5588
5589 if(!ignorescreen)
5590 {
5591 if(flag==mfHAMMER||flag==mfSTRIKE) // Takes precedence over Secret Tile and Armos->Secret
5592 {
5593 findentrance(bx,by,mfHAMMER,true);
5594 findentrance(bx,by,mfSTRIKE,true);
5595 }
5596 else if(flag2==mfHAMMER||flag2==mfSTRIKE)
5597 {
5598 findentrance(bx,by,mfHAMMER,true);
5599 findentrance(bx,by,mfSTRIKE,true);
5600 }
5601 else if((flag >= 16)&&(flag <= 31))
5602 {
5603 s->data[i] = s->secretcombo[(s->sflag[i])-16+4];
5604 s->cset[i] = s->secretcset[(s->sflag[i])-16+4];
5605 s->sflag[i] = s->secretflag[(s->sflag[i])-16+4];
5606 }
5607 else if(flag == mfARMOS_SECRET)
5608 {
5609 s->data[i] = s->secretcombo[sSTAIRS];
5610 s->cset[i] = s->secretcset[sSTAIRS];
5611 s->sflag[i] = s->secretflag[sSTAIRS];
5612 sfx(tmpscr->secretsfx);
5613 }
5614 else if((flag2 >= 16)&&(flag2 <= 31))
5615 {
5616 s->data[i] = s->secretcombo[(s->sflag[i])-16+4];
5617 s->cset[i] = s->secretcset[(s->sflag[i])-16+4];
5618 s->sflag[i] = s->secretflag[(s->sflag[i])-16+4];
5619 }
5620 else if(flag2 == mfARMOS_SECRET)
5621 {
5622 s->data[i] = s->secretcombo[sSTAIRS];
5623 s->cset[i] = s->secretcset[sSTAIRS];
5624 s->sflag[i] = s->secretflag[sSTAIRS];
5625 sfx(tmpscr->secretsfx);
5626 }
5627 else pound = true;
5628 }
5629
5630 if(!ignoreffc)
5631 {
5632 if(flag3==mfHAMMER||flag3==mfSTRIKE)
5633 {
5634 findentrance(fx,fy,mfHAMMER,true);
5635 findentrance(fx,fy,mfSTRIKE,true);
5636 }
5637 else
5638 {
5639 s->ffcs[current_ffcombo].incData(1);
5640 }
5641 }
5642
5643 if(!ignorescreen)
5644 {
5645 if(pound)
5646 s->data[i]+=1;
5647
5648 set_bit(screengrid,i,1);
5649
5650 if((flag==mfARMOS_ITEM||flag2==mfARMOS_ITEM) && (!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN)))
5651 {
5652 items.add(new item((zfix)bx, (zfix)by, (zfix)0, tmpscr->catchall, ipONETIME2 + ipBIGRANGE + ipHOLDUP | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0), 0));
5653 sfx(tmpscr->secretsfx);
5654 }
5655
5656 if(type==cPOUND && get_bit(quest_rules,qr_MORESOUNDS))
5657 sfx(QMisc.miscsfx[sfxHAMMERPOUND],int32_t(bx));
5658
5659 putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]);
5660 }
5661
5662 if(!ignoreffc)
5663 {
5664 set_bit(ffcgrid,current_ffcombo,1);
5665
5666 if(type2==cPOUND && get_bit(quest_rules,qr_MORESOUNDS))
5667 sfx(QMisc.miscsfx[sfxHAMMERPOUND],int32_t(bx));
5668 }
5669
5670 return;
5671 }
5672
5673 //defend results should match defence types.
5674 //RETURN VALUES:
5675 // -1 iGNORE WEAPON
5676 // 0 No effects
5677 // 1 Effects, weapon is not ignored or removed
5678 int32_t HeroClass::defend(weapon *w)
5679 {
5680 int32_t def = conv_edef_unblockable(defence[w->id], w->unblockable);
5681 switch(def)
5682 {
5683 case edNORMAL: return 1;
5684 case edHALFDAMAGE: // : IMPLEMENTED : Take half damage
5685 {
5686 w->power *= 0.5;
5687 return 1;
5688 }
5689 case edQUARTDAMAGE:
5690 {
5691 w->power *= 0.25;
5692 return 1;
5693 }
5694 case edSTUNONLY:
5695 {
5696 setStunClock(120);
5697 return 1;
5698 }
5699 case edSTUNORCHINK: // : IMPLEMENTED : If damage > 0, stun instead. Else, bounce off.
5700 {
5701 if (w->power > 0)
5702 {
5703 setStunClock(120);
5704 return 1;
5705 }
5706 else
5707 {
5708 sfx(WAV_CHINK,pan(int32_t(x)));
5709 w->dead = 0;
5710 return -1;
5711 }
5712 }
5713 case edSTUNORIGNORE: // : IMPLEMENTED : If damage > 0, stun instead. Else, ignore.
5714 {
5715 if (w->power > 0)
5716 {
5717 setStunClock(120);
5718 return 1;
5719 }
5720 else
5721 {
5722 return -1;
5723 }
5724 }
5725 case edCHINKL1: // : IMPLEMENTED : Bounces off, plays SFX_CHINK
5726 {
5727 if (w->power < 1)
5728 {
5729 sfx(WAV_CHINK,pan(int32_t(x)));
5730 w->dead = 0;
5731 return -1;
5732 }
5733 else
5734 {
5735 return 1;
5736 }
5737 }
5738 case edCHINKL2: // : IMPLEMENTED : Bounce off unless damage >= 2
5739 {
5740 if (w->power < 2)
5741 {
5742 sfx(WAV_CHINK,pan(int32_t(x)));
5743 w->dead = 0;
5744 return -1;
5745 }
5746 else
5747 {
5748 return 1;
5749 }
5750 }
5751 case edCHINKL4: //: IMPLEMENTED : Bounce off unless damage >= 4
5752 {
5753 if (w->power < 4)
5754 {
5755 sfx(WAV_CHINK,pan(int32_t(x)));
5756 w->dead = 0;
5757 return -1;
5758 }
5759 else
5760 {
5761 return 1;
5762 }
5763 }
5764 case edCHINKL6: // : IMPLEMENTED : Bounce off unless damage >= 6
5765 {
5766 if (w->power < 6)
5767 {
5768 sfx(WAV_CHINK,pan(int32_t(x)));
5769 w->dead = 0;
5770 return -1;
5771 }
5772 else
5773 {
5774 return 1;
5775 }
5776 }
5777 case edCHINKL8: // : IMPLEMENTED : Bounce off unless damage >= 8
5778 {
5779 if (w->power < 8)
5780 {
5781 sfx(WAV_CHINK,pan(int32_t(x)));
5782 w->dead = 0;
5783 return -1;
5784 }
5785 else
5786 {
5787 return 1;
5788 }
5789 }
5790 case edCHINK: // : IMPLEMENTED : Bounces off, plays SFX_CHINK
5791 {
5792 sfx(WAV_CHINK,pan(int32_t(x)));
5793 w->dead = 0;
5794 return -1;
5795 }
5796 case edIGNOREL1: // : IMPLEMENTED : Ignore unless damage > 1.
5797 {
5798 if (w->power < 1)
5799 {
5800 return -1;
5801 }
5802 else return 1;
5803 }
5804 case edIGNORE: // : IMPLEMENTED : Do Nothing
5805 {
5806 return -1;
5807 }
5808 case ed1HKO: // : IMPLEMENTED : One-hit knock-out
5809 {
5810 game->set_life(0);
5811 return 1;
5812 }
5813 case edCHINKL10: //: IMPLEMENTED : If damage is less than 10
5814 {
5815 if (w->power < 10)
5816 {
5817 sfx(WAV_CHINK,pan(int32_t(x)));
5818 w->dead = 0;
5819 return -1;
5820 }
5821 else
5822 {
5823 return 1;
5824 }
5825 }
5826 case ed2x: // : IMPLEMENTED : Double damage.
5827 {
5828 w->power *= 2;
5829 return 1;
5830 }
5831 case ed3x: // : IMPLEMENTED : Triple Damage.
5832 {
5833 w->power *= 3;
5834 return 1;
5835 }
5836 case ed4x: // : IMPLEMENTED : 4x damage.
5837 {
5838 w->power *= 4;
5839 return 1;
5840 }
5841 case edHEAL: // : IMPLEMENTED : Gain the weapon damage in HP.
5842 {
5843 //sfx(WAV_HEAL,pan(int32_t(x)));
5844 game->set_life(zc_min(game->get_life()+w->power, game->get_maxlife()));
5845 w->dead = 0;
5846 return -1;
5847 }
5848
5849 case edFREEZE: return 1; //Not IMPLEMENTED
5850
5851 case edLEVELDAMAGE: //Damage * item level
5852 {
5853 w->power *= w->family_level;
5854 return 1;
5855 }
5856 case edLEVELREDUCTION: //Damage / item level
5857 {
5858 if ( w->family_level > 0 )
5859 {
5860 w->power /= w->family_level;
5861 }
5862 else w->power = 0;
5863 return 1;
5864 }
5865
5866 //edLEVELCHINK2, //If item level is < 2: This needs a weapon variable that is set by
5867 //edLEVELCHINK3, //If item level is < 3: the item that generates it (itemdata::level stored to
5868 //edLEVELCHINK4, //If item level is < 4: weapon::level, or something similar; then a check to
5869 //edLEVELCHINK5, //If item level is < 5: read weapon::level in hit detection.
5870
5871 //edSHOCK, //buzz blob
5872
5873
5874 case edBREAKSHIELD: //destroy the player's present shield
5875 {
5876 w->power = 0;
5877 w->dead = 0;
5878 int32_t itemid = getCurrentShield();
5879 //sfx(WAV_BREAKSHIELD,pan(int32_t(x)));
5880 if(itemsbuf[itemid].flags&ITEM_EDIBLE)
5881 game->set_item(itemid, false);
5882 //Remove Hero's shield
5883 return -1;
5884 }
5885
5886
5887
5888 default: return 0;
5889 }
5890 }
5891
5892 int32_t HeroClass::compareDir(int32_t other)
5893 {
5894 if(other != NORMAL_DIR(other))
5895 return 0; //*sigh* scripts expect dirs >=8 to NOT hit shields...
5896 int32_t ret = 0;
5897 auto d = (shield_forcedir < 0) ? dir : shield_forcedir;
5898 switch(d)
5899 {
5900 case up:
5901 {
5902 switch(X_DIR(other))
5903 {
5904 case left:
5905 ret |= CMPDIR_RIGHT;
5906 break;
5907 case right:
5908 ret |= CMPDIR_LEFT;
5909 break;
5910 }
5911 switch(Y_DIR(other))
5912 {
5913 case up:
5914 ret |= CMPDIR_BACK;
5915 break;
5916 case down:
5917 ret |= CMPDIR_FRONT;
5918 break;
5919 }
5920 break;
5921 }
5922 case down:
5923 {
5924 switch(X_DIR(other))
5925 {
5926 case left:
5927 ret |= CMPDIR_LEFT;
5928 break;
5929 case right:
5930 ret |= CMPDIR_RIGHT;
5931 break;
5932 }
5933 switch(Y_DIR(other))
5934 {
5935 case up:
5936 ret |= CMPDIR_FRONT;
5937 break;
5938 case down:
5939 ret |= CMPDIR_BACK;
5940 break;
5941 }
5942 break;
5943 }
5944 case left:
5945 {
5946 switch(X_DIR(other))
5947 {
5948 case left:
5949 ret |= CMPDIR_BACK;
5950 break;
5951 case right:
5952 ret |= CMPDIR_FRONT;
5953 break;
5954 }
5955 switch(Y_DIR(other))
5956 {
5957 case up:
5958 ret |= CMPDIR_LEFT;
5959 break;
5960 case down:
5961 ret |= CMPDIR_RIGHT;
5962 break;
5963 }
5964 break;
5965 }
5966 case right:
5967 {
5968 switch(X_DIR(other))
5969 {
5970 case left:
5971 ret |= CMPDIR_FRONT;
5972 break;
5973 case right:
5974 ret |= CMPDIR_BACK;
5975 break;
5976 }
5977 switch(Y_DIR(other))
5978 {
5979 case up:
5980 ret |= CMPDIR_RIGHT;
5981 break;
5982 case down:
5983 ret |= CMPDIR_LEFT;
5984 break;
5985 }
5986 break;
5987 }
5988 }
5989 return ret;
5990 }
5991
5992 bool compareShield(int32_t cmpdir, itemdata const& shield)
5993 {
5994 bool standard = !(shield.flags&ITEM_FLAG9) || usingActiveShield();
5995 if(standard) //Use standard sides, either a passive shield, or a held active shield
5996 {
5997 if((cmpdir&CMPDIR_FRONT) && (shield.flags&ITEM_FLAG1))
5998 return true;
5999 else if((cmpdir&CMPDIR_BACK) && (shield.flags&ITEM_FLAG2))
6000 return true;
6001 else if((cmpdir&CMPDIR_LEFT) && (shield.flags&ITEM_FLAG3))
6002 return true;
6003 else if((cmpdir&CMPDIR_RIGHT) && (shield.flags&ITEM_FLAG4))
6004 return true;
6005 }
6006 else //Active Shield that is NOT held down
6007 {
6008 if((cmpdir&CMPDIR_FRONT) && (shield.flags&ITEM_FLAG5))
6009 return true;
6010 else if((cmpdir&CMPDIR_BACK) && (shield.flags&ITEM_FLAG6))
6011 return true;
6012 else if((cmpdir&CMPDIR_LEFT) && (shield.flags&ITEM_FLAG7))
6013 return true;
6014 else if((cmpdir&CMPDIR_RIGHT) && (shield.flags&ITEM_FLAG8))
6015 return true;
6016 }
6017 return false;
6018 }
6019
6020 1653 int32_t HeroClass::EwpnHit()
6021 {
6022
2/2
✓ Branch 0 taken 1653 times.
✓ Branch 1 taken 171 times.
1824 for(int32_t i=0; i<Ewpns.Count(); i++)
6023 {
6024
1/2
✓ Branch 0 taken 171 times.
✗ Branch 1 not taken.
171 if(Ewpns.spr(i)->hit(x+7,y+7-fakez,z,2,2,1))
6025 {
6026 weapon *ew = (weapon*)(Ewpns.spr(i));
6027
6028 if((ew->ignoreHero)==true || ew->fallclk|| ew->drownclk)
6029 break;
6030
6031 int32_t defresult = defend(ew);
6032 if ( defresult == -1 ) return -1; //The weapon did something special, but it is otherwise ignored, possibly killed by defend().
6033
6034 if(ew->id==ewWind)
6035 {
6036 xofs=1000;
6037 action=freeze; FFCore.setHeroAction(freeze);
6038 ew->misc=999; // in enemy wind
6039 attackclk=0;
6040 return -1;
6041 }
6042
6043 switch(ew->id)
6044 {
6045 case ewLitBomb:
6046 case ewBomb:
6047 case ewLitSBomb:
6048 case ewSBomb:
6049 return i;
6050 }
6051
6052 int32_t itemid = getCurrentShield(false);
6053 if(itemid<0 || !(checkbunny(itemid) && checkmagiccost(itemid))) return i;
6054 itemdata const& shield = itemsbuf[itemid];
6055 auto cmpdir = compareDir(ew->dir);
6056 bool hitshield = compareShield(cmpdir, shield);
6057
6058
6059 if(!hitshield || (action==attacking||action==sideswimattacking) || action==swimming || action == sideswimming || action == sideswimattacking || charging > 0 || spins > 0 || hopclk==0xFF)
6060 {
6061 return i;
6062 }
6063
6064 paymagiccost(itemid);
6065
6066 bool reflect = false;
6067
6068 switch(ew->id)
6069 {
6070 case ewFireball2:
6071 case ewFireball:
6072 if(ew->type & 1) //Boss fireball
6073 {
6074 if(!(shield.misc1 & (shFIREBALL2)))
6075 return i;
6076
6077 reflect = ((shield.misc2 & shFIREBALL2) != 0);
6078 }
6079 else
6080 {
6081 if(!(shield.misc1 & (shFIREBALL)))
6082 return i;
6083
6084 reflect = ((shield.misc2 & shFIREBALL) != 0);
6085 }
6086
6087 break;
6088
6089 case ewMagic:
6090 if(!(shield.misc1 & shMAGIC))
6091 return i;
6092
6093 reflect = ((shield.misc2 & shMAGIC) != 0);
6094 break;
6095
6096 case ewSword:
6097 if(!(shield.misc1 & shSWORD))
6098 return i;
6099
6100 reflect = ((shield.misc2 & shSWORD) != 0);
6101 break;
6102
6103 case ewFlame:
6104 if(!(shield.misc1 & shFLAME))
6105 return i;
6106
6107 reflect = ((shield.misc2 & shFLAME) != 0); // Actually isn't reflected.
6108 break;
6109
6110 case ewRock:
6111 if(!(shield.misc1 & shROCK))
6112 return i;
6113
6114 reflect = (shield.misc2 & shROCK);
6115 break;
6116
6117 case ewArrow:
6118 if(!(shield.misc1 & shARROW))
6119 return i;
6120
6121 reflect = ((shield.misc2 & shARROW) != 0); // Actually isn't reflected.
6122 break;
6123
6124 case ewBrang:
6125 if(!(shield.misc1 & shBRANG))
6126 return i;
6127
6128 break;
6129
6130 default: // Just throw the script weapons in here...
6131 if(ew->id>=wScript1 && ew->id<=wScript10)
6132 {
6133 if(!(shield.misc1 & shSCRIPT))
6134 return i;
6135
6136 reflect = ((shield.misc2 & shSCRIPT) != 0);
6137 }
6138
6139 break;
6140 }
6141
6142 if(reflect && (ew->unblockable&WPNUNB_REFL))
6143 reflect = false;
6144 if(!reflect && (ew->unblockable&WPNUNB_SHLD))
6145 return i;
6146
6147 int32_t oldid = ew->id;
6148 ew->onhit(false, reflect ? 2 : 1, dir);
6149
6150 if(ew->id != oldid) // changed type from ewX to wX
6151 {
6152 // ew->power*=game->get_hero_dmgmult();
6153 Lwpns.add(ew);
6154 Ewpns.remove(ew);
6155 ew->isLWeapon = true; //Make sure this gets set everywhere!
6156 }
6157
6158 if(ew->id==wRefMagic)
6159 {
6160 ew->ignoreHero=true;
6161 ew->ignorecombo=-1;
6162 }
6163
6164 sfx(shield.usesound,pan(x.getInt()));
6165 }
6166 171 }
6167
6168 1653 return -1;
6169 1653 }
6170
6171 1653 int32_t HeroClass::LwpnHit() //only here to check magic hits
6172 {
6173
2/2
✓ Branch 0 taken 1620 times.
✓ Branch 1 taken 733 times.
2353 for(int32_t i=0; i<Lwpns.Count(); i++)
6174
2/2
✓ Branch 0 taken 700 times.
✓ Branch 1 taken 33 times.
733 if(Lwpns.spr(i)->hit(x+7,y+7-fakez,z,2,2,1))
6175 {
6176 33 weapon *lw = (weapon*)(Lwpns.spr(i));
6177
6178
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if((lw->ignoreHero)==true)
6179 break;
6180
6181
4/8
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 33 times.
33 if (!(lw->id == wRefFireball || lw->id == wRefMagic || lw->id == wRefBeam || lw->id == wRefRock)) return -1;
6182 int32_t itemid = getCurrentShield(false);
6183 if(itemid<0 || !(checkbunny(itemid) && checkmagiccost(itemid))) return i;
6184 itemdata const& shield = itemsbuf[itemid];
6185 auto cmpdir = compareDir(lw->dir);
6186 bool hitshield = compareShield(cmpdir, shield);
6187 bool reflect = false;
6188
6189 switch(lw->id)
6190 {
6191 case wRefFireball:
6192 if(itemid<0)
6193 return i;
6194
6195 if(lw->type & 1) //Boss fireball
6196 return i;
6197
6198 if(!(shield.misc1 & (shFIREBALL)))
6199 return i;
6200
6201 reflect = ((shield.misc2 & shFIREBALL) != 0);
6202 break;
6203
6204 case wRefMagic:
6205 if(itemid<0)
6206 return i;
6207
6208 if(!(shield.misc1 & shMAGIC))
6209 return i;
6210
6211 reflect = ((shield.misc2 & shMAGIC) != 0);
6212 break;
6213
6214 case wRefBeam:
6215 if(itemid<0)
6216 return i;
6217
6218 if(!(shield.misc1 & shSWORD))
6219 return i;
6220
6221 reflect = ((shield.misc2 & shSWORD) != 0);
6222 break;
6223
6224 case wRefRock:
6225 if(itemid<0)
6226 return i;
6227
6228 if(!(shield.misc1 & shROCK))
6229 return i;
6230
6231 reflect = (shield.misc2 & shROCK);
6232 break;
6233
6234 default:
6235 return -1;
6236 }
6237
6238 if(!hitshield || (action==attacking||action==sideswimattacking) || action==swimming || action == sideswimming || action == sideswimattacking || hopclk==0xFF)
6239 return i;
6240
6241 if(itemid<0 || !(checkbunny(itemid) && checkmagiccost(itemid))) return i;
6242
6243 paymagiccost(itemid);
6244
6245 lw->onhit(false, 1+reflect, dir);
6246 lw->ignoreHero=true;
6247 lw->ignorecombo=-1;
6248 sfx(shield.usesound,pan(x.getInt()));
6249 }
6250
6251 1620 return -1;
6252 1653 }
6253
6254 3400 void HeroClass::checkhit()
6255 {
6256
2/2
✓ Branch 0 taken 1512 times.
✓ Branch 1 taken 1888 times.
3400 if(checkhero==true)
6257 {
6258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(hclk>0)
6259 {
6260 --hclk;
6261 }
6262
6263
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(NayrusLoveShieldClk>0)
6264 {
6265 --NayrusLoveShieldClk;
6266
6267 if(NayrusLoveShieldClk == 0 && nayruitem != -1)
6268 {
6269 stop_sfx(itemsbuf[nayruitem].usesound);
6270 stop_sfx(itemsbuf[nayruitem].usesound+1);
6271 nayruitem = -1;
6272 }
6273 else if(get_bit(quest_rules,qr_MORESOUNDS) && !(NayrusLoveShieldClk&0xF00) && nayruitem != -1)
6274 {
6275 stop_sfx(itemsbuf[nayruitem].usesound);
6276 cont_sfx(itemsbuf[nayruitem].usesound+1);
6277 }
6278 }
6279 1888 }
6280
6281
3/4
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 1512 times.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
3400 if(hclk<39 && action==gothit)
6282 {
6283 action=none; FFCore.setHeroAction(none);
6284 }
6285
6286
4/6
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 1512 times.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1888 times.
3400 if(hclk<39 && (action==swimhit || action == sideswimhit))
6287 {
6288 SetSwim();
6289 }
6290
6291
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3400 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3400 if(hclk>=40 && action==gothit)
6292 {
6293 int val = check_pitslide();
6294 if(((ladderx+laddery) && ((hitdir&2)==ladderdir))||(!(ladderx+laddery)))
6295 {
6296 for(int32_t i=0; i<4; i++)
6297 {
6298 switch(hitdir)
6299 {
6300 case up:
6301 if(hit_walkflag(x,y+(bigHitbox?-1:7),2)||(x.getInt()&7?hit_walkflag(x+16,y+(bigHitbox?-1:7),1):0))
6302 {
6303 action=none; FFCore.setHeroAction(none);
6304 }
6305 else if (val == -1) --y;
6306
6307 break;
6308
6309 case down:
6310 if(hit_walkflag(x,y+16,2)||(x.getInt()&7?hit_walkflag(x+16,y+16,1):0))
6311 {
6312 action=none; FFCore.setHeroAction(none);
6313 }
6314 else if (val == -1) ++y;
6315
6316 break;
6317
6318 case left:
6319 if(hit_walkflag(x-1,y+(bigHitbox?0:8),1)||hit_walkflag(x-1,y+8,1)||(y.getInt()&7?hit_walkflag(x-1,y+16,1):0))
6320 {
6321 action=none; FFCore.setHeroAction(none);
6322 }
6323 else if (val == -1) --x;
6324
6325 break;
6326
6327 case right:
6328 if(hit_walkflag(x+16,y+(bigHitbox?0:8),1)||hit_walkflag(x+16,y+8,1)||(y.getInt()&7?hit_walkflag(x+16,y+16,1):0))
6329 {
6330 action=none; FFCore.setHeroAction(none);
6331 }
6332 else if (val == -1) ++x;
6333
6334 break;
6335 }
6336 }
6337 }
6338 }
6339
6340
12/20
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 1512 times.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1888 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1888 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1888 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1888 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1888 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1888 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 1888 times.
✓ Branch 18 taken 1512 times.
✓ Branch 19 taken 1512 times.
3400 if(hclk>0 || inlikelike == 1 || action==inwind || action==drowning || action==lavadrowning || action==sidedrowning || inwallm || isDiving() || (action==hopping && hopclk<255))
6341 {
6342 3024 return;
6343 }
6344
6345
2/2
✓ Branch 0 taken 2268 times.
✓ Branch 1 taken 1888 times.
4156 for(int32_t i=0; i<Lwpns.Count(); i++)
6346 {
6347 2268 sprite *s = Lwpns.spr(i);
6348 2268 int32_t itemid = ((weapon*)(Lwpns.spr(i)))->parentitem;
6349 //if ( itemdbuf[parentitem].flags&ITEM_FLAGS3 ) //can damage Hero
6350 //if ( itemsbuf[parentitem].misc1 > 0 ) //damages Hero by this amount.
6351
8/14
✗ Branch 0 not taken.
✓ Branch 1 taken 2268 times.
✓ Branch 2 taken 756 times.
✓ Branch 3 taken 1512 times.
✓ Branch 4 taken 756 times.
✓ Branch 5 taken 756 times.
✓ Branch 6 taken 756 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 756 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 756 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
2268 if((!(itemid==-1&&get_bit(quest_rules,qr_FIREPROOFHERO)||((itemid>-1&&itemsbuf[itemid].family==itype_candle||itemsbuf[itemid].family==itype_book)&&(itemsbuf[itemid].flags & ITEM_FLAG3)))) && (scriptcoldet&1) && !fallclk && (!superman || !get_bit(quest_rules,qr_FIREPROOFHERO2)))
6352 {
6353
2/10
✓ Branch 0 taken 756 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 756 times.
✗ Branch 9 not taken.
756 if(s->id==wFire && (superman ? (diagonalMovement?s->hit(x+4,y+4-fakez,z,7,7,1):s->hit(x+7,y+7-fakez,z,2,2,1)) : s->hit(this))&&
6354 (itemid < 0 || itemsbuf[itemid].family!=itype_dinsfire))
6355 {
6356 std::vector<int32_t> &ev = FFCore.eventData;
6357 ev.clear();
6358 ev.push_back(lwpn_dp(i)*10000);
6359 ev.push_back(s->hitdir(x,y,16,16,dir)*10000);
6360 ev.push_back(0);
6361 ev.push_back(NayrusLoveShieldClk>0?10000:0);
6362 ev.push_back(48*10000);
6363 ev.push_back(ZSD_LWPN*10000);
6364 ev.push_back(s->getUID());
6365
6366 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_1);
6367 int32_t dmg = ev[0]/10000;
6368 bool nullhit = ev[2] != 0;
6369
6370 if(nullhit) {ev.clear(); return;}
6371
6372 //Args: 'damage (post-ring)','hitdir','nullifyhit','type:npc','npc uid'
6373 ev[0] = ringpower(dmg)*10000;
6374
6375 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_2);
6376 dmg = ev[0]/10000;
6377 int32_t hdir = ev[1]/10000;
6378 nullhit = ev[2] != 0;
6379 bool nayrulove = ev[3] != 0;
6380 int32_t iframes = ev[4] / 10000;
6381 ev.clear();
6382 if(nullhit) return;
6383 if(!nayrulove)
6384 {
6385 game->set_life(zc_max(game->get_life()-dmg,0));
6386 }
6387
6388 hitdir = hdir;
6389
6390 if (action != rafting && action != freeze && action != sideswimfreeze)
6391 {
6392 if (IsSideSwim())
6393 {
6394 action=sideswimhit; FFCore.setHeroAction(sideswimhit);
6395 }
6396 else if (action == swimming || hopclk == 0xFF)
6397 {
6398 action=swimhit; FFCore.setHeroAction(swimhit);
6399 }
6400 else
6401 {
6402 action=gothit; FFCore.setHeroAction(gothit);
6403 }
6404 }
6405
6406 if(charging > 0 || spins > 0 || attack == wSword || attack == wHammer)
6407 {
6408 spins = charging = attackclk = 0;
6409 attack=none;
6410 tapping = false;
6411 }
6412
6413 hclk=iframes;
6414 sfx(getHurtSFX(),pan(x.getInt()));
6415 return;
6416 }
6417 756 }
6418
6419 // check enemy weapons true, 1, -1
6420 //
6421
1/2
✓ Branch 0 taken 756 times.
✗ Branch 1 not taken.
756 if((itemsbuf[itemid].flags & ITEM_FLAG6))
6422 {
6423 if(s->id==wBrang || (s->id==wHookshot&&!pull_hero))
6424 {
6425 int32_t itemid = ((weapon*)s)->parentitem>-1 ? ((weapon*)s)->parentitem :
6426 directWpn>-1 ? directWpn : current_item_id(s->id==wHookshot ? (((weapon*)s)->family_class == itype_switchhook ? itype_switchhook : itype_hookshot) : itype_brang);
6427 itemid = vbound(itemid, 0, MAXITEMS-1);
6428
6429 for(int32_t j=0; j<Ewpns.Count(); j++)
6430 {
6431 sprite *t = Ewpns.spr(j);
6432
6433 if(s->hit(t->x+7,t->y+7-t->fakez,t->z,2,2,1))
6434 {
6435 bool reflect = false;
6436 // sethitHeroUID(HIT_BY_EWEAPON,j); //set that Hero was hit by a specific eweapon index.
6437 switch(t->id)
6438 {
6439 case ewBrang:
6440 if(!(itemsbuf[itemid].misc3 & shBRANG)) break;
6441
6442 reflect = ((itemsbuf[itemid].misc4 & shBRANG) != 0);
6443 goto killweapon;
6444
6445 case ewArrow:
6446 if(!(itemsbuf[itemid].misc3 & shARROW)) break;
6447
6448 reflect = ((itemsbuf[itemid].misc4 & shARROW) != 0);
6449 goto killweapon;
6450
6451 case ewRock:
6452 if(!(itemsbuf[itemid].misc3 & shROCK)) break;
6453
6454 reflect = ((itemsbuf[itemid].misc4 & shROCK) != 0);
6455 goto killweapon;
6456
6457 case ewFireball2:
6458 case ewFireball:
6459 {
6460 int32_t mask = (((weapon*)t)->type&1 ? shFIREBALL2 : shFIREBALL);
6461
6462 if(!(itemsbuf[itemid].misc3 & mask)) break;
6463
6464 reflect = ((itemsbuf[itemid].misc4 & mask) != 0);
6465 goto killweapon;
6466 }
6467
6468 case ewSword:
6469 if(!(itemsbuf[itemid].misc3 & shSWORD)) break;
6470
6471 reflect = ((itemsbuf[itemid].misc4 & shSWORD) != 0);
6472 goto killweapon;
6473
6474 case wRefMagic:
6475 case ewMagic:
6476 if(!(itemsbuf[itemid].misc3 & shMAGIC)) break;
6477
6478 reflect = ((itemsbuf[itemid].misc4 & shMAGIC) != 0);
6479 goto killweapon;
6480
6481 case wScript1:
6482 case wScript2:
6483 case wScript3:
6484 case wScript4:
6485 case wScript5:
6486 case wScript6:
6487 case wScript7:
6488 case wScript8:
6489 case wScript9:
6490 case wScript10:
6491 if(!(itemsbuf[itemid].misc3 & shSCRIPT)) break;
6492
6493 reflect = ((itemsbuf[itemid].misc4 & shSCRIPT) != 0);
6494 goto killweapon;
6495
6496 case ewLitBomb:
6497 case ewLitSBomb:
6498 killweapon:
6499 ((weapon*)s)->dead=1;
6500 weapon *ew = ((weapon*)t);
6501 int32_t oldid = ew->id;
6502 ew->onhit(true, reflect ? 2 : 1, s->dir);
6503
6504 if(ew->id != oldid || (ew->id>=wScript1 && ew->id<=wScript10)) // changed type from ewX to wX... Except for script weapons
6505 {
6506 Lwpns.add(ew);
6507 Ewpns.remove(ew);
6508 ew->isLWeapon = true; //Make sure this gets set everywhere!
6509 }
6510
6511 if(ew->id==wRefMagic)
6512 {
6513 ew->ignoreHero=true;
6514 ew->ignorecombo=-1;
6515 }
6516
6517 break;
6518 }
6519
6520 break;
6521 }
6522 }
6523 }
6524 }
6525
6526
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
756 if((itemsbuf[itemid].flags & ITEM_FLAG2)||(itemid==-1&&get_bit(quest_rules,qr_OUCHBOMBS)))
6527 {
6528
2/10
✓ Branch 0 taken 756 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 756 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
756 if(((s->id==wBomb)||(s->id==wSBomb)) && s->hit(this) && !superman && (scriptcoldet&1) && !fallclk)
6529 {
6530 std::vector<int32_t> &ev = FFCore.eventData;
6531 ev.clear();
6532 ev.push_back(((((weapon*)s)->parentitem>-1 ? itemsbuf[((weapon*)s)->parentitem].misc3 : ((weapon*)s)->power) *game->get_hp_per_heart())*10000);
6533 ev.push_back(s->hitdir(x,y,16,16,dir)*10000);
6534 ev.push_back(0);
6535 ev.push_back(NayrusLoveShieldClk>0?10000:0);
6536 ev.push_back(48*10000);
6537 ev.push_back(ZSD_LWPN*10000);
6538 ev.push_back(s->getUID());
6539
6540 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_1);
6541 int32_t dmg = ev[0]/10000;
6542 bool nullhit = ev[2] != 0;
6543
6544 if(nullhit) {ev.clear(); return;}
6545
6546 //Args: 'damage (post-ring)','hitdir','nullifyhit','type:npc','npc uid'
6547 ev[0] = ringpower(dmg)*10000;
6548
6549 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_2);
6550 dmg = ev[0]/10000;
6551 int32_t hdir = ev[1]/10000;
6552 nullhit = ev[2] != 0;
6553 bool nayrulove = ev[3] != 0;
6554 int32_t iframes = ev[4] / 10000;
6555 ev.clear();
6556 if(nullhit) return;
6557 if(!nayrulove)
6558 {
6559 game->set_life(zc_min(game->get_maxlife(), zc_max(game->get_life()-dmg,0)));
6560 }
6561
6562 hitdir = hdir;
6563
6564 if (action != rafting && action != freeze && action != sideswimfreeze)
6565 {
6566 if (IsSideSwim())
6567 {
6568 action=sideswimhit; FFCore.setHeroAction(sideswimhit);
6569 }
6570 else if (action == swimming || hopclk == 0xFF)
6571 {
6572 action=swimhit; FFCore.setHeroAction(swimhit);
6573 }
6574 else
6575 {
6576 action=gothit; FFCore.setHeroAction(gothit);
6577 }
6578 }
6579
6580 if(charging > 0 || spins > 0 || attack == wSword || attack == wHammer)
6581 {
6582 spins = charging = attackclk = 0;
6583 attack=none;
6584 tapping = false;
6585 }
6586
6587 hclk=iframes;
6588 sfx(getHurtSFX(),pan(x.getInt()));
6589 return;
6590 }
6591 756 }
6592
6593
3/8
✓ Branch 0 taken 756 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 756 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 756 times.
✗ Branch 7 not taken.
756 if(hclk==0 && s->id==wWind && s->hit(x+7,y+7-fakez,z,2,2,1) && !fairyclk)
6594 {
6595 std::vector<int32_t> &ev = FFCore.eventData;
6596 ev.clear();
6597 ev.push_back(0);
6598 ev.push_back(s->dir*10000);
6599 ev.push_back(0);
6600 ev.push_back(0);
6601 ev.push_back(ZSD_LWPN*10000);
6602 ev.push_back(s->getUID());
6603
6604 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_1);
6605 bool nullhit = ev[2] != 0;
6606 if(nullhit) {ev.clear(); return;}
6607
6608 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_2);
6609 int32_t hdir = ev[1]/10000;
6610 nullhit = ev[2] != 0;
6611 ev.clear();
6612 if(nullhit) return;
6613
6614 reset_hookshot();
6615 xofs=1000;
6616 action=inwind; FFCore.setHeroAction(inwind);
6617 dir=s->dir=hdir;
6618 spins = charging = attackclk = 0;
6619
6620 // In case Hero used two whistles in a row, summoning two whirlwinds,
6621 // check which whistle's whirlwind picked him up so the correct
6622 // warp ring will be used
6623 int32_t whistle=((weapon*)s)->parentitem;
6624
6625 if(whistle>-1 && itemsbuf[whistle].family==itype_whistle)
6626 whistleitem=whistle;
6627
6628 return;
6629 }
6630 756 }
6631
6632
5/8
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✓ Branch 3 taken 235 times.
✓ Branch 4 taken 1653 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1653 times.
3541 if(action==rafting || action==freeze || action==sideswimfreeze ||
6633
4/8
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1653 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1653 times.
✗ Branch 7 not taken.
1653 action==casting || action==sideswimcasting || action==drowning || action==lavadrowning || action==sidedrowning)
6634 235 return;
6635
6636 1653 int32_t hit2 = -1;
6637 1653 do
6638 {
6639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
1653 hit2 = diagonalMovement ? GuyHitFrom(hit2+1,x+4,y+4-fakez,z,8,8,hzsz)
6640 1653 : GuyHitFrom(hit2+1,x+7,y+7-fakez,z,2,2,hzsz);
6641
6642
1/2
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
1653 if(hit2!=-1)
6643 {
6644 if (hithero(hit2) == 0) return;
6645 }
6646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
1653 } while (hit2 != -1);
6647
3/6
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1653 times.
1653 if (superman || !(scriptcoldet&1) || fallclk) return;
6648 1653 hit2 = LwpnHit();
6649
6650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
1653 if(hit2!=-1)
6651 {
6652 weapon* lwpnspr = (weapon*)Lwpns.spr(hit2);
6653 std::vector<int32_t> &ev = FFCore.eventData;
6654 ev.clear();
6655 ev.push_back((lwpn_dp(hit2)*10000));
6656 ev.push_back(lwpnspr->hitdir(x,y,16,16,dir)*10000);
6657 ev.push_back(0);
6658 ev.push_back(NayrusLoveShieldClk>0?10000:0);
6659 ev.push_back(48*10000);
6660 ev.push_back(ZSD_LWPN*10000);
6661 ev.push_back(lwpnspr->getUID());
6662
6663 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_1);
6664 int32_t dmg = ev[0]/10000;
6665 bool nullhit = ev[2] != 0;
6666
6667 if(nullhit) {ev.clear(); return;}
6668
6669 //Args: 'damage (post-ring)','hitdir','nullifyhit','type:npc','npc uid'
6670 ev[0] = ringpower(dmg)*10000;
6671
6672 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_2);
6673 dmg = ev[0]/10000;
6674 int32_t hdir = ev[1]/10000;
6675 nullhit = ev[2] != 0;
6676 bool nayrulove = ev[3] != 0;
6677 int32_t iframes = ev[4] / 10000;
6678 ev.clear();
6679 if(nullhit) return;
6680 if(!nayrulove)
6681 {
6682 game->set_life(zc_max(game->get_life()-dmg,0));
6683 sethitHeroUID(HIT_BY_LWEAPON,(hit2+1));
6684 sethitHeroUID(HIT_BY_LWEAPON_UID,lwpnspr->getUID());
6685 }
6686
6687 hitdir = hdir;
6688 lwpnspr->onhit(false);
6689
6690 if (IsSideSwim())
6691 {
6692 action=sideswimhit; FFCore.setHeroAction(sideswimhit);
6693 }
6694 else if(action==swimming || hopclk==0xFF)
6695 {
6696 action=swimhit; FFCore.setHeroAction(swimhit);
6697 }
6698 else
6699 {
6700 action=gothit; FFCore.setHeroAction(gothit);
6701 }
6702
6703 hclk=iframes;
6704
6705 if(charging > 0 || spins > 0 || attack == wSword || attack == wHammer)
6706 {
6707 spins = charging = attackclk = 0;
6708 attack=none;
6709 tapping = false;
6710 }
6711
6712 sfx(getHurtSFX(),pan(x.getInt()));
6713 return;
6714 }
6715
6716 //else { sethitHeroUID(HIT_BY_LWEAPON,(0)); //fails to clear
6717
6718 1653 hit2 = EwpnHit();
6719
6720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
1653 if(hit2!=-1)
6721 {
6722 weapon* ewpnspr = (weapon*)Ewpns.spr(hit2);
6723 std::vector<int32_t> &ev = FFCore.eventData;
6724 ev.clear();
6725 ev.push_back((ewpn_dp(hit2)*10000));
6726 ev.push_back(ewpnspr->hitdir(x,y,16,16,dir)*10000);
6727 ev.push_back(0);
6728 ev.push_back(NayrusLoveShieldClk>0?10000:0);
6729 ev.push_back(48*10000);
6730 ev.push_back(ZSD_EWPN*10000);
6731 ev.push_back(ewpnspr->getUID());
6732
6733 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_1);
6734 int32_t dmg = ev[0]/10000;
6735 bool nullhit = ev[2] != 0;
6736
6737 if(nullhit) {ev.clear(); return;}
6738
6739 //Args: 'damage (post-ring)','hitdir','nullifyhit','type:npc','npc uid'
6740 ev[0] = ringpower(dmg)*10000;
6741
6742 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_2);
6743 dmg = ev[0]/10000;
6744 int32_t hdir = ev[1]/10000;
6745 nullhit = ev[2] != 0;
6746 bool nayrulove = ev[3] != 0;
6747 int32_t iframes = ev[4] / 10000;
6748 ev.clear();
6749 if(nullhit) return;
6750 if(!nayrulove)
6751 {
6752 game->set_life(zc_max(game->get_life()-dmg,0));
6753 sethitHeroUID(HIT_BY_EWEAPON,(hit2+1));
6754 sethitHeroUID(HIT_BY_EWEAPON_UID,ewpnspr->getUID());
6755 }
6756
6757 hitdir = hdir;
6758 ewpnspr->onhit(false);
6759
6760 if (IsSideSwim())
6761 {
6762 action=sideswimhit; FFCore.setHeroAction(sideswimhit);
6763 }
6764 else if(action==swimming || hopclk==0xFF)
6765 {
6766 action=swimhit; FFCore.setHeroAction(swimhit);
6767 }
6768 else
6769 {
6770 action=gothit; FFCore.setHeroAction(gothit);
6771 }
6772
6773 hclk=iframes;
6774
6775 if(charging > 0 || spins > 0 || attack == wSword || attack == wHammer)
6776 {
6777 spins = charging = attackclk = 0;
6778 attack=none;
6779 tapping = false;
6780 }
6781
6782 sfx(getHurtSFX(),pan(x.getInt()));
6783 return;
6784 }
6785 //else { sethitHeroUID(HIT_BY_EWEAPON,(0)); } //fails to clear
6786
6787 // The rest of this method deals with damage combos, which can be jumped over.
6788
2/4
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✗ Branch 3 not taken.
1653 if((z>0 || fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) return;
6789
6790 1653 int32_t dx1 = (int32_t)x+8-(tmpscr->csensitive);
6791 1653 int32_t dx2 = (int32_t)x+8+(tmpscr->csensitive-1);
6792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
1653 int32_t dy1 = (int32_t)y+(bigHitbox?8:12)-(bigHitbox?tmpscr->csensitive:(tmpscr->csensitive+1)/2);
6793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
1653 int32_t dy2 = (int32_t)y+(bigHitbox?8:12)+(bigHitbox?tmpscr->csensitive-1:((tmpscr->csensitive+1)/2)-1);
6794
6795
2/2
✓ Branch 0 taken 1653 times.
✓ Branch 1 taken 1653 times.
3306 for(int32_t i=get_bit(quest_rules, qr_DMGCOMBOLAYERFIX) ? 1 : -1; i>=-1; i--) // Layers 0, 1 and 2!!
6796 1653 (void)checkdamagecombos(dx1,dx2,dy1,dy2,i);
6797 1888 }
6798
6799 bool HeroClass::checkdamagecombos(int32_t dx, int32_t dy)
6800 {
6801 return checkdamagecombos(dx,dx,dy,dy);
6802 }
6803
6804 void HeroClass::doHit(int32_t hdir)
6805 {
6806 hitdir = hdir;
6807
6808 if (action != rafting && action != freeze && action != sideswimfreeze)
6809 {
6810 if (IsSideSwim())
6811 {
6812 action=sideswimhit; FFCore.setHeroAction(sideswimhit);
6813 }
6814 else if (action == swimming || hopclk == 0xFF)
6815 {
6816 action=swimhit; FFCore.setHeroAction(swimhit);
6817 }
6818 else
6819 {
6820 action=gothit; FFCore.setHeroAction(gothit);
6821 }
6822 }
6823
6824 hclk=48;
6825
6826 if(charging > 0 || spins > 0 || attack == wSword || attack == wHammer)
6827 {
6828 spins = charging = attackclk = 0;
6829 attack=none;
6830 tapping = false;
6831 }
6832
6833 sfx(getHurtSFX(),pan(x.getInt()));
6834 }
6835
6836 1653 bool HeroClass::checkdamagecombos(int32_t dx1, int32_t dx2, int32_t dy1, int32_t dy2, int32_t layer, bool solid, bool do_health_check) //layer = -1, solid = false, do_health_check = true
6837 {
6838
3/6
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1653 times.
1653 if(hclk || superman || fallclk)
6839 return false;
6840
6841 1653 int32_t hp_mod[4] = {0};
6842 int32_t cid[8];
6843 1653 byte hasKB = 0;
6844
6845 {
6846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
1653 cid[0] = layer>-1?MAPCOMBO2(layer,dx1,dy1):MAPCOMBO(dx1,dy1);
6847 1653 newcombo& cmb = combobuf[cid[0]];
6848
2/4
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✗ Branch 3 not taken.
1653 if ( !(cmb.triggerflags[0] & combotriggerONLYGENTRIG) && combo_class_buf[cmb.type].modify_hp_amount)
6849 {
6850 if(cmb.usrflags&cflag1)
6851 hp_mod[0] = cmb.attributes[0] / -10000L;
6852 else
6853 hp_mod[0]=combo_class_buf[cmb.type].modify_hp_amount;
6854 if(!(cmb.usrflags&cflag2))
6855 hasKB |= 1<<0;
6856 }
6857 }
6858 {
6859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
1653 cid[1] = layer>-1?MAPCOMBO2(layer,dx1,dy2):MAPCOMBO(dx1,dy2);
6860 1653 newcombo& cmb = combobuf[cid[1]];
6861
2/4
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✗ Branch 3 not taken.
1653 if ( !(cmb.triggerflags[0] & combotriggerONLYGENTRIG) && combo_class_buf[cmb.type].modify_hp_amount)
6862 {
6863 if(cmb.usrflags&cflag1)
6864 hp_mod[1] = cmb.attributes[0] / -10000L;
6865 else
6866 hp_mod[1]=combo_class_buf[cmb.type].modify_hp_amount;
6867 if(!(cmb.usrflags&cflag2))
6868 hasKB |= 1<<1;
6869 }
6870 }
6871 {
6872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
1653 cid[2] = layer>-1?MAPCOMBO2(layer,dx2,dy1):MAPCOMBO(dx2,dy1);
6873 1653 newcombo& cmb = combobuf[cid[2]];
6874
2/4
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✗ Branch 3 not taken.
1653 if ( !(cmb.triggerflags[0] & combotriggerONLYGENTRIG) && combo_class_buf[cmb.type].modify_hp_amount)
6875 {
6876 if(cmb.usrflags&cflag1)
6877 hp_mod[2] = cmb.attributes[0] / -10000L;
6878 else
6879 hp_mod[2]=combo_class_buf[cmb.type].modify_hp_amount;
6880 if(!(cmb.usrflags&cflag2))
6881 hasKB |= 1<<2;
6882 }
6883 }
6884 {
6885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
1653 cid[3] = layer>-1?MAPCOMBO2(layer,dx2,dy2):MAPCOMBO(dx2,dy2);
6886 1653 newcombo& cmb = combobuf[cid[3]];
6887
2/4
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✗ Branch 3 not taken.
1653 if ( !(cmb.triggerflags[0] & combotriggerONLYGENTRIG) && combo_class_buf[cmb.type].modify_hp_amount)
6888 {
6889 if(cmb.usrflags&cflag1)
6890 hp_mod[3] = cmb.attributes[0] / -10000L;
6891 else
6892 hp_mod[3]=combo_class_buf[cmb.type].modify_hp_amount;
6893 if(!(cmb.usrflags&cflag2))
6894 hasKB |= 1<<3;
6895 }
6896 }
6897
6898 1653 int32_t bestcid=0;
6899 1653 int32_t hp_modtotal=0;
6900
2/2
✓ Branch 0 taken 1648 times.
✓ Branch 1 taken 5 times.
1653 if (!_effectflag(dx1,dy1,1, layer)) {hp_mod[0] = 0; hasKB &= ~(1<<0);}
6901
2/2
✓ Branch 0 taken 1646 times.
✓ Branch 1 taken 7 times.
1653 if (!_effectflag(dx1,dy2,1, layer)) {hp_mod[1] = 0; hasKB &= ~(1<<1);}
6902
2/2
✓ Branch 0 taken 1648 times.
✓ Branch 1 taken 5 times.
1653 if (!_effectflag(dx2,dy1,1, layer)) {hp_mod[2] = 0; hasKB &= ~(1<<2);}
6903
2/2
✓ Branch 0 taken 1646 times.
✓ Branch 1 taken 7 times.
1653 if (!_effectflag(dx2,dy2,1, layer)) {hp_mod[3] = 0; hasKB &= ~(1<<3);}
6904
6905
2/2
✓ Branch 0 taken 3306 times.
✓ Branch 1 taken 1653 times.
4959 for (int32_t i = 0; i <= 1; ++i)
6906 {
6907
1/2
✓ Branch 0 taken 3306 times.
✗ Branch 1 not taken.
3306 if(tmpscr2[i].valid!=0)
6908 {
6909 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
6910 {
6911 if (combobuf[MAPCOMBO2(i,dx1,dy1)].type == cBRIDGE && !_walkflag_layer(dx1,dy1,1, &(tmpscr2[i]))) {hp_mod[0] = 0; hasKB &= ~(1<<0);}
6912 if (combobuf[MAPCOMBO2(i,dx1,dy2)].type == cBRIDGE && !_walkflag_layer(dx1,dy2,1, &(tmpscr2[i]))) {hp_mod[1] = 0; hasKB &= ~(1<<1);}
6913 if (combobuf[MAPCOMBO2(i,dx2,dy1)].type == cBRIDGE && !_walkflag_layer(dx2,dy1,1, &(tmpscr2[i]))) {hp_mod[2] = 0; hasKB &= ~(1<<2);}
6914 if (combobuf[MAPCOMBO2(i,dx2,dy2)].type == cBRIDGE && !_walkflag_layer(dx2,dy2,1, &(tmpscr2[i]))) {hp_mod[3] = 0; hasKB &= ~(1<<3);}
6915 }
6916 else
6917 {
6918 if (combobuf[MAPCOMBO2(i,dx1,dy1)].type == cBRIDGE && _effectflag_layer(dx1,dy1,1, &(tmpscr2[i]))) {hp_mod[0] = 0; hasKB &= ~(1<<0);}
6919 if (combobuf[MAPCOMBO2(i,dx1,dy2)].type == cBRIDGE && _effectflag_layer(dx1,dy2,1, &(tmpscr2[i]))) {hp_mod[1] = 0; hasKB &= ~(1<<1);}
6920 if (combobuf[MAPCOMBO2(i,dx2,dy1)].type == cBRIDGE && _effectflag_layer(dx2,dy1,1, &(tmpscr2[i]))) {hp_mod[2] = 0; hasKB &= ~(1<<2);}
6921 if (combobuf[MAPCOMBO2(i,dx2,dy2)].type == cBRIDGE && _effectflag_layer(dx2,dy2,1, &(tmpscr2[i]))) {hp_mod[3] = 0; hasKB &= ~(1<<3);}
6922 }
6923 }
6924 3306 }
6925
6926
2/2
✓ Branch 0 taken 6612 times.
✓ Branch 1 taken 1653 times.
8265 for(int32_t i=0; i<4; i++)
6927 {
6928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6612 times.
6612 if(get_bit(quest_rules,qr_DMGCOMBOPRI))
6929 {
6930 if(hp_modtotal >= 0) //Okay, if it's over 0, it's healing Hero.
6931 {
6932 if(hp_mod[i] < hp_modtotal)
6933 {
6934 hp_modtotal = hp_mod[i];
6935 bestcid = cid[i];
6936 }
6937 }
6938 else if(hp_mod[i] < 0) //If it's under 0, it's hurting Hero.
6939 {
6940 if(hp_mod[i] > hp_modtotal)
6941 {
6942 hp_modtotal = hp_mod[i];
6943 bestcid = cid[i];
6944 }
6945 }
6946 }
6947
1/2
✓ Branch 0 taken 6612 times.
✗ Branch 1 not taken.
6612 else if(hp_mod[i] < hp_modtotal)
6948 {
6949 hp_modtotal = hp_mod[i];
6950 bestcid = cid[i];
6951 }
6952 6612 }
6953
6954 {
6955 1653 cid[4] = MAPFFCOMBO(dx1,dy1);
6956 1653 newcombo& cmb = combobuf[cid[4]];
6957
2/4
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✗ Branch 3 not taken.
1653 if ( !(cmb.triggerflags[0] & combotriggerONLYGENTRIG) && combo_class_buf[cmb.type].modify_hp_amount)
6958 {
6959 if(cmb.usrflags&cflag1 )
6960 hp_mod[0] = cmb.attributes[0]/10000L;
6961 else
6962 hp_mod[0]=combo_class_buf[cmb.type].modify_hp_amount;
6963 if(!(cmb.usrflags&cflag2))
6964 hasKB |= 1<<4;
6965 }
6966 }
6967 {
6968 1653 cid[5] = MAPFFCOMBO(dx1,dy2);
6969 1653 newcombo& cmb = combobuf[cid[5]];
6970
2/4
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✗ Branch 3 not taken.
1653 if ( !(cmb.triggerflags[0] & combotriggerONLYGENTRIG) && combo_class_buf[cmb.type].modify_hp_amount)
6971 {
6972 if(cmb.usrflags&cflag1 )
6973 hp_mod[1] = cmb.attributes[0]/10000L;
6974 else
6975 hp_mod[1]=combo_class_buf[cmb.type].modify_hp_amount;
6976 if(!(cmb.usrflags&cflag2))
6977 hasKB |= 1<<5;
6978 }
6979 }
6980 {
6981 1653 cid[6] = MAPFFCOMBO(dx2,dy1);
6982 1653 newcombo& cmb = combobuf[cid[6]];
6983
2/4
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✗ Branch 3 not taken.
1653 if ( !(cmb.triggerflags[0] & combotriggerONLYGENTRIG) && combo_class_buf[cmb.type].modify_hp_amount)
6984 {
6985 if(cmb.usrflags&cflag1 )
6986 hp_mod[2] = cmb.attributes[0]/10000L;
6987 else
6988 hp_mod[2]=combo_class_buf[cmb.type].modify_hp_amount;
6989 if(!(cmb.usrflags&cflag2))
6990 hasKB |= 1<<6;
6991 }
6992 }
6993 {
6994 1653 cid[7] = MAPFFCOMBO(dx2,dy2);
6995 1653 newcombo& cmb = combobuf[cid[7]];
6996
2/4
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✗ Branch 3 not taken.
1653 if ( !(cmb.triggerflags[0] & combotriggerONLYGENTRIG) && combo_class_buf[cmb.type].modify_hp_amount)
6997 {
6998 if(cmb.usrflags&cflag1 )
6999 hp_mod[3] = cmb.attributes[0]/10000L;
7000 else
7001 hp_mod[3]=combo_class_buf[cmb.type].modify_hp_amount;
7002 if(!(cmb.usrflags&cflag2))
7003 hasKB |= 1<<7;
7004 }
7005 }
7006
7007 1653 int32_t bestffccid = 0;
7008 1653 int32_t hp_modtotalffc = 0;
7009
7010
2/2
✓ Branch 0 taken 3306 times.
✓ Branch 1 taken 1653 times.
4959 for (int32_t i = 0; i <= 1; ++i)
7011 {
7012
1/2
✓ Branch 0 taken 3306 times.
✗ Branch 1 not taken.
3306 if(tmpscr2[i].valid!=0)
7013 {
7014 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
7015 {
7016 if (combobuf[MAPCOMBO2(i,dx1,dy1)].type == cBRIDGE && !_walkflag_layer(dx1,dy1,1, &(tmpscr2[i]))) {hp_mod[0] = 0; hasKB &= ~(1<<4);}
7017 if (combobuf[MAPCOMBO2(i,dx1,dy2)].type == cBRIDGE && !_walkflag_layer(dx1,dy2,1, &(tmpscr2[i]))) {hp_mod[1] = 0; hasKB &= ~(1<<5);}
7018 if (combobuf[MAPCOMBO2(i,dx2,dy1)].type == cBRIDGE && !_walkflag_layer(dx2,dy1,1, &(tmpscr2[i]))) {hp_mod[2] = 0; hasKB &= ~(1<<6);}
7019 if (combobuf[MAPCOMBO2(i,dx2,dy2)].type == cBRIDGE && !_walkflag_layer(dx2,dy2,1, &(tmpscr2[i]))) {hp_mod[3] = 0; hasKB &= ~(1<<7);}
7020 }
7021 else
7022 {
7023 if (combobuf[MAPCOMBO2(i,dx1,dy1)].type == cBRIDGE && _effectflag_layer(dx1,dy1,1, &(tmpscr2[i]))) {hp_mod[0] = 0; hasKB &= ~(1<<4);}
7024 if (combobuf[MAPCOMBO2(i,dx1,dy2)].type == cBRIDGE && _effectflag_layer(dx1,dy2,1, &(tmpscr2[i]))) {hp_mod[1] = 0; hasKB &= ~(1<<5);}
7025 if (combobuf[MAPCOMBO2(i,dx2,dy1)].type == cBRIDGE && _effectflag_layer(dx2,dy1,1, &(tmpscr2[i]))) {hp_mod[2] = 0; hasKB &= ~(1<<6);}
7026 if (combobuf[MAPCOMBO2(i,dx2,dy2)].type == cBRIDGE && _effectflag_layer(dx2,dy2,1, &(tmpscr2[i]))) {hp_mod[3] = 0; hasKB &= ~(1<<7);}
7027 }
7028 }
7029 3306 }
7030
7031
2/2
✓ Branch 0 taken 6612 times.
✓ Branch 1 taken 1653 times.
8265 for(int32_t i=0; i<4; i++)
7032 {
7033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6612 times.
6612 if(get_bit(quest_rules,qr_DMGCOMBOPRI))
7034 {
7035 if(hp_modtotalffc >= 0)
7036 {
7037 if(hp_mod[i] < hp_modtotalffc)
7038 {
7039 hp_modtotalffc = hp_mod[i];
7040 bestffccid = cid[4+i];
7041 }
7042 }
7043 else if(hp_mod[i] < 0)
7044 {
7045 if(hp_mod[i] > hp_modtotalffc)
7046 {
7047 hp_modtotalffc = hp_mod[i];
7048 bestffccid = cid[4+i];
7049 }
7050 }
7051 }
7052
1/2
✓ Branch 0 taken 6612 times.
✗ Branch 1 not taken.
6612 else if(hp_mod[i] < hp_modtotalffc)
7053 {
7054 hp_modtotalffc = hp_mod[i];
7055 bestffccid = cid[4+i];
7056 }
7057 6612 }
7058
7059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
1653 int32_t hp_modmin = zc_min(hp_modtotal, hp_modtotalffc);
7060
1/2
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
1653 if(hp_modtotalffc < hp_modmin) bestcid = bestffccid;
7061
7062 1653 bool global_defring = ((itemsbuf[current_item_id(itype_ring)].flags & ITEM_FLAG1));
7063 1653 bool global_perilring = ((itemsbuf[current_item_id(itype_perilring)].flags & ITEM_FLAG1));
7064 1653 bool current_ring = ((tmpscr->flags6&fTOGGLERINGDAMAGE) != 0);
7065
1/2
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
1653 if(current_ring)
7066 {
7067 global_defring = !global_defring;
7068 global_perilring = !global_perilring;
7069 }
7070 1653 int32_t itemid = current_item_id(itype_boots);
7071
7072
1/2
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
1653 bool bootsnosolid = itemid >= 0 && 0 != (itemsbuf[itemid].flags & ITEM_FLAG1);
7073
1/2
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
1653 bool ignoreBoots = itemid >= 0 && (itemsbuf[itemid].flags & ITEM_FLAG3);
7074
7075
1/2
✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
1653 if(hp_modmin<0)
7076 {
7077 if((itemid<0) || ignoreBoots || (tmpscr->flags5&fDAMAGEWITHBOOTS) || (4<<current_item_power(itype_boots)<(abs(hp_modmin))) || (solid && bootsnosolid) || !(checkbunny(itemid) && checkmagiccost(itemid)))
7078 {
7079 if (!do_health_check) return true;
7080 std::vector<int32_t> &ev = FFCore.eventData;
7081 ev.clear();
7082 ev.push_back(-hp_modmin*10000);
7083 ev.push_back((hasKB ? dir^1 : -1)*10000);
7084 ev.push_back(0);
7085 ev.push_back(NayrusLoveShieldClk>0?10000:0);
7086 ev.push_back(48*10000);
7087 ev.push_back(ZSD_COMBODATA*10000);
7088 ev.push_back(bestcid);
7089
7090 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_1);
7091 int32_t dmg = ev[0]/10000;
7092 bool nullhit = ev[2] != 0;
7093
7094 if(nullhit) {ev.clear(); return false;}
7095
7096 //Args: 'damage (post-ring)','hitdir','nullifyhit','type:npc','npc uid'
7097 ev[0] = ringpower(dmg, !global_perilring, !global_defring)*10000;
7098
7099 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_2);
7100 dmg = ev[0]/10000;
7101 int32_t hdir = ev[1]/10000;
7102 nullhit = ev[2] != 0;
7103 bool nayrulove = ev[3] != 0;
7104 int32_t iframes = ev[4] / 10000;
7105 ev.clear();
7106 if(nullhit) return false;
7107
7108 if(!nayrulove)
7109 {
7110 game->set_life(zc_max(game->get_life()-dmg,0));
7111 }
7112
7113 hitdir = hdir;
7114 doHit(hitdir);
7115 hclk = iframes;
7116 return true;
7117 }
7118 else if (do_health_check) paymagiccost(itemid); // Boots are successful
7119 }
7120
7121 1653 return false;
7122 1653 }
7123
7124 int32_t HeroClass::hithero(int32_t hit2, int32_t force_hdir)
7125 {
7126 if(force_hdir > 3) force_hdir = -1;
7127 enemy* enemyptr = (enemy*)guys.spr(hit2);
7128 if(!enemyptr) return 0;
7129 //printf("Stomp check: %d <= 12, %d < %d\n", int32_t((y+16)-(((enemy*)guys.spr(hit2))->y)), (int32_t)falling_oldy, (int32_t)y);
7130 int32_t stompid = current_item_id(itype_stompboots);
7131 if(current_item(itype_stompboots) && checkbunny(stompid) && checkmagiccost(stompid) && (stomping ||
7132 ((z+fakez) > (enemyptr->z+(enemyptr->fakez))) ||
7133 ((isSideViewHero() && (y+16)-(enemyptr->y)<=14) && falling_oldy<y)))
7134 {
7135 paymagiccost(stompid);
7136 hit_enemy(hit2,wStomp,itemsbuf[stompid].power*game->get_hero_dmgmult(),x,y,0,stompid);
7137
7138 if(itemsbuf[stompid].flags & ITEM_DOWNGRADE)
7139 game->set_item(stompid,false);
7140
7141 // Stomp Boots script
7142 if(itemsbuf[stompid].script != 0 && !(item_doscript[stompid] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)))
7143 {
7144 //clear the item script stack for a new script
7145 ri = &(itemScriptData[stompid]);
7146 for ( int32_t q = 0; q < 1024; q++ ) item_stack[stompid][q] = 0xFFFF;
7147 ri->Clear();
7148 //itemScriptData[(stompid & 0xFFF)].Clear();
7149 //for ( int32_t q = 0; q < 1024; q++ ) item_stack[(stompid & 0xFFF)][q] = 0;
7150 //ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[stompid].script, stompid & 0xFFF);
7151 item_doscript[stompid] = 1;
7152 itemscriptInitialised[stompid] = 0;
7153 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[stompid].script, stompid);
7154 }
7155
7156 return -1;
7157 }
7158 else if(superman || !(scriptcoldet&1) || fallclk)
7159 return 0;
7160 //!TODO SOLIDPUSH Enemy flag to make them not deal contact damage
7161 //!Add a flag check to this if:
7162 else if (!(enemyptr->stunclk==0 && enemyptr->frozenclock==0 && (!get_bit(quest_rules, qr_SAFEENEMYFADE) || enemyptr->fading != fade_flicker)
7163 && (enemyptr->d->family != eeGUY || enemyptr->dmisc1)))
7164 {
7165 return -1;
7166 }
7167
7168 std::vector<int32_t> &ev = FFCore.eventData;
7169 ev.clear();
7170 //Args: 'damage (pre-ring)','hitdir','nullifyhit','type:npc','npc uid'
7171 ev.push_back((enemy_dp(hit2) *10000));
7172 ev.push_back((force_hdir>-1 ? force_hdir : ((sprite*)enemyptr)->hitdir(x,y,16,16,dir))*10000);
7173 ev.push_back(0);
7174 ev.push_back(NayrusLoveShieldClk>0?10000:0);
7175 ev.push_back(48*10000);
7176 ev.push_back(ZSD_NPC*10000);
7177 ev.push_back(enemyptr->getUID());
7178
7179 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_1);
7180 int32_t dmg = ev[0] / 10000;
7181 bool nullhit = ev[2] != 0;
7182
7183 if(nullhit) {ev.clear(); return -1;}
7184
7185 //Args: 'damage (post-ring)','hitdir','nullifyhit','type:npc','npc uid'
7186 ev[0] = ((ringpower(dmg)*10000));
7187
7188 throwGenScriptEvent(GENSCR_EVENT_HERO_HIT_2);
7189 dmg = ev[0] / 10000;
7190 int32_t hdir = ev[1] / 10000;
7191 nullhit = ev[2] != 0;
7192 bool nayrulove = ev[3] != 0;
7193 int32_t iframes = ev[4] / 10000;
7194 ev.clear();
7195
7196 if(nullhit) return -1;
7197
7198 if(!nayrulove)
7199 {
7200 game->set_life(zc_max(game->get_life()-dmg,0));
7201 sethitHeroUID(HIT_BY_NPC,(hit2+1));
7202 sethitHeroUID(HIT_BY_NPC_UID,enemyptr->getUID());
7203 }
7204
7205 hitdir = hdir;
7206 if (IsSideSwim())
7207 {
7208 action=sideswimhit; FFCore.setHeroAction(sideswimhit);
7209 }
7210 else if(action==swimming || hopclk==0xFF)
7211 {
7212 action=swimhit; FFCore.setHeroAction(swimhit);
7213 }
7214 else
7215 {
7216 action=gothit; FFCore.setHeroAction(gothit);
7217 }
7218
7219 hclk=iframes;
7220 sfx(getHurtSFX(),pan(x.getInt()));
7221
7222 if(charging > 0 || spins > 0 || attack == wSword || attack == wHammer)
7223 {
7224 spins = charging = attackclk = 0;
7225 attack=none;
7226 tapping = false;
7227 }
7228
7229 enemy_scored(hit2);
7230 int32_t dm7 = enemyptr->dmisc7;
7231 int32_t dm8 = enemyptr->dmisc8;
7232
7233 switch(enemyptr->family)
7234 {
7235 case eeWALLM:
7236 if(enemyptr->hp>0)
7237 {
7238 GrabHero(hit2);
7239 inwallm=true;
7240 action=none; FFCore.setHeroAction(none);
7241 }
7242 break;
7243
7244 //case eBUBBLEST:
7245 //case eeBUBBLE:
7246 case eeWALK:
7247 {
7248 int32_t itemid = current_item_id(itype_whispring);
7249 //I can only assume these are supposed to be int32_t, not bool ~pkmnfrk
7250 int32_t sworddivisor = ((itemid>-1 && itemsbuf[itemid].misc1 & 1) ? itemsbuf[itemid].power : 1);
7251 int32_t itemdivisor = ((itemid>-1 && itemsbuf[itemid].misc1 & 2) ? itemsbuf[itemid].power : 1);
7252
7253 switch(dm7)
7254 {
7255 case e7tTEMPJINX:
7256 if(dm8==0 || dm8==2)
7257 if(swordclk>=0 && !(sworddivisor==0))
7258 swordclk=150;
7259
7260 if(dm8==1 || dm8==2)
7261 if(itemclk>=0 && !(itemdivisor==0))
7262 itemclk=150;
7263
7264 break;
7265
7266 case e7tPERMJINX:
7267 if(dm8==0 || dm8==2)
7268 if(sworddivisor) swordclk=(itemid >-1 && itemsbuf[itemid].flags & ITEM_FLAG1)? int32_t(150/sworddivisor) : -1;
7269
7270 if(dm8==1 || dm8==2)
7271 if(itemdivisor) itemclk=(itemid >-1 && itemsbuf[itemid].flags & ITEM_FLAG1)? int32_t(150/itemdivisor) : -1;
7272
7273 break;
7274
7275 case e7tUNJINX:
7276 if(dm8==0 || dm8==2)
7277 swordclk=0;
7278
7279 if(dm8==1 || dm8==2)
7280 itemclk=0;
7281
7282 break;
7283
7284 case e7tTAKEMAGIC:
7285 game->change_dmagic(-dm8*game->get_magicdrainrate());
7286 break;
7287
7288 case e7tTAKERUPEES:
7289 game->change_drupy(-dm8);
7290 break;
7291
7292 case e7tDRUNK:
7293 drunkclk += dm8;
7294 break;
7295 }
7296 verifyAWpn();
7297 if(dm7 >= e7tEATITEMS)
7298 {
7299 EatHero(hit2);
7300 inlikelike=(dm7 == e7tEATHURT ? 2:1);
7301 action=none; FFCore.setHeroAction(none);
7302 }
7303 }
7304 }
7305 return 0;
7306 }
7307
7308 void HeroClass::addsparkle(int32_t wpn)
7309 {
7310 //return;
7311 weapon *w = (weapon*)Lwpns.spr(wpn);
7312 int32_t itemid = w->parentitem;
7313
7314 if(itemid<0)
7315 return;
7316
7317 int32_t itemtype = itemsbuf[itemid].family;
7318
7319 if(itemtype!=itype_cbyrna && frame%4)
7320 return;
7321
7322 int32_t wpn2 = (itemtype==itype_cbyrna) ? itemsbuf[itemid].wpn4 : itemsbuf[itemid].wpn2;
7323 int32_t wpn3 = (itemtype==itype_cbyrna) ? itemsbuf[itemid].wpn5 : itemsbuf[itemid].wpn3;
7324 // Either one (wpn2) or the other (wpn3). If both are present, randomise.
7325 int32_t sparkle_type = (!wpn2 ? (!wpn3 ? 0 : wpn3) : (!wpn3 ? wpn2 : (zc_oldrand()&1 ? wpn2 : wpn3)));
7326 int32_t direction=w->dir;
7327
7328 if(sparkle_type)
7329 {
7330 int32_t h=0;
7331 int32_t v=0;
7332
7333 if(w->dir==right||w->dir==r_up||w->dir==r_down)
7334 {
7335 h=-1;
7336 }
7337
7338 if(w->dir==left||w->dir==l_up||w->dir==l_down)
7339 {
7340 h=1;
7341 }
7342
7343 if(w->dir==down||w->dir==l_down||w->dir==r_down)
7344 {
7345 v=-1;
7346 }
7347
7348 if(w->dir==up||w->dir==l_up||w->dir==r_up)
7349 {
7350 v=1;
7351 }
7352
7353 // Damaging boomerang sparkle?
7354 if(wpn3 && itemtype==itype_brang)
7355 {
7356 // If the boomerang just bounced, flip the sparkle direction so it doesn't hit
7357 // whatever it just bounced off of if it's shielded from that direction.
7358 if(w->misc==1 && w->clk2>256 && w->clk2<272)
7359 direction=oppositeDir[direction];
7360 }
7361 if(itemtype==itype_brang && get_bit(quest_rules, qr_WRONG_BRANG_TRAIL_DIR)) direction = 0;
7362 zfix x = w->x+(itemtype==itype_cbyrna ? 2 : zc_oldrand()%4)+(h*4);
7363 zfix y = w->y+(itemtype==itype_cbyrna ? 2 : zc_oldrand()%4)+(v*4)-w->fakez;
7364 Lwpns.add(new weapon(x, y, w->z, sparkle_type==wpn3 ? wFSparkle : wSSparkle,sparkle_type,0,direction,itemid,getUID(),false,false,true, 0, sparkle_type));
7365 weapon *w = (weapon*)(Lwpns.spr(Lwpns.Count()-1));
7366 }
7367 }
7368
7369 // For wPhantoms
7370 void HeroClass::addsparkle2(int32_t type1, int32_t type2)
7371 {
7372 if(frame%4) return;
7373
7374 int32_t arrow = -1;
7375
7376 for(int32_t i=0; i<Lwpns.Count(); i++)
7377 {
7378 weapon *w = (weapon*)Lwpns.spr(i);
7379
7380 if(w->id == wPhantom && w->type == type1)
7381 {
7382 arrow = i;
7383 break;
7384 }
7385 }
7386
7387 if(arrow==-1)
7388 {
7389 return;
7390 }
7391
7392 zfix x = (Lwpns.spr(arrow)->x-3)+(zc_oldrand()%7);
7393 zfix y = (Lwpns.spr(arrow)->y-3)+(zc_oldrand()%7)-Lwpns.spr(arrow)->fakez;
7394 Lwpns.add(new weapon(x, y, Lwpns.spr(arrow)->z, wPhantom, type2,0,0,((weapon*)Lwpns.spr(arrow))->parentitem,-1));
7395 }
7396
7397 //cleans up decorations that exit the bounds of the screen for a int32_t time, to prevebt them wrapping around.
7398 1888 void HeroClass::PhantomsCleanup()
7399 {
7400
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(Lwpns.idCount(wPhantom))
7401 {
7402 for(int32_t i=0; i<Lwpns.Count(); i++)
7403 {
7404 weapon *w = ((weapon *)Lwpns.spr(i));
7405 if ( w->id == wPhantom && !w->isScriptGenerated() )
7406 {
7407 if ( w->x < -10000 || w->y > 10000 || w->x < -10000 || w->y > 10000 )
7408 {
7409 Lwpns.remove(w);
7410 }
7411 }
7412 }
7413 }
7414 1888 }
7415
7416 //Waitframe handler for refilling operations
7417 static void do_refill_waitframe()
7418 {
7419 put_passive_subscr(framebuf,&QMisc,0,passive_subscreen_offset,game->should_show_time(),sspUP);
7420 if(get_bit(quest_rules, qr_PASSIVE_SUBSCRIPT_RUNS_WHEN_GAME_IS_FROZEN))
7421 {
7422 script_drawing_commands.Clear();
7423 if(DMaps[currdmap].passive_sub_script != 0)
7424 ZScriptVersion::RunScript(SCRIPT_PASSIVESUBSCREEN, DMaps[currdmap].passive_sub_script, currdmap);
7425 if(passive_subscreen_waitdraw && DMaps[currdmap].passive_sub_script != 0 && passive_subscreen_doscript != 0)
7426 {
7427 ZScriptVersion::RunScript(SCRIPT_PASSIVESUBSCREEN, DMaps[currdmap].passive_sub_script, currdmap);
7428 passive_subscreen_waitdraw = false;
7429 }
7430 do_script_draws(framebuf, tmpscr, 0, playing_field_offset);
7431 }
7432 advanceframe(true);
7433 }
7434 //Special handler if it's a "fairy revive"
7435 static void do_death_refill_waitframe()
7436 {
7437 //!TODO Run a new script slot each frame here, before calling do_refill_waitframe()
7438 //This script should be able to draw a 'fairy saving the player' animation -Em
7439 do_refill_waitframe();
7440 }
7441
7442 static size_t find_bottle_for_slot(size_t slot, bool unowned=false)
7443 {
7444 int32_t found_unowned = -1;
7445 for(int q = 0; q < MAXITEMS; ++q)
7446 {
7447 if(itemsbuf[q].family == itype_bottle && itemsbuf[q].misc1 == slot)
7448 {
7449 if(game->get_item(q))
7450 return q;
7451 if(unowned)
7452 found_unowned = q;
7453 }
7454 }
7455 return found_unowned;
7456 }
7457
7458 int32_t getPushDir(int32_t flag)
7459 {
7460 switch(flag)
7461 {
7462 case mfPUSHUD: case mfPUSH4: case mfPUSHU: case mfPUSHUDNS:
7463 case mfPUSH4NS: case mfPUSHUNS: case mfPUSHUDINS: case mfPUSH4INS:
7464 case mfPUSHUINS:
7465 return up;
7466 case mfPUSHD: case mfPUSHDNS: case mfPUSHDINS:
7467 return down;
7468 case mfPUSHLR: case mfPUSHL: case mfPUSHLRNS: case mfPUSHLNS:
7469 case mfPUSHLRINS: case mfPUSHLINS:
7470 return left;
7471 case mfPUSHR: case mfPUSHRNS: case mfPUSHRINS:
7472 return right;
7473 }
7474 return -1;
7475 }
7476
7477 // returns true when game over
7478 5664 bool HeroClass::animate(int32_t)
7479 {
7480 5664 int32_t lsave=0;
7481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5664 times.
5664 if(immortal > 0)
7482 --immortal;
7483 5664 prompt_combo = 0;
7484
2/2
✓ Branch 0 taken 3776 times.
✓ Branch 1 taken 1888 times.
5664 if (onpassivedmg)
7485 {
7486 3776 onpassivedmg=false;
7487 3776 }
7488
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 else if (damageovertimeclk)
7489 {
7490 damageovertimeclk = 0;
7491 }
7492
7493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5664 times.
5664 if(cheats_execute_goto)
7494 {
7495 didpit=true;
7496 pitx=x;
7497 pity=y;
7498 dowarp(3,0);
7499 cheats_execute_goto=false;
7500 solid_update(false);
7501 return false;
7502 }
7503
7504
1/2
✓ Branch 0 taken 5664 times.
✗ Branch 1 not taken.
5664 if(cheats_execute_light)
7505 {
7506 naturaldark = !naturaldark;
7507 lighting(false, false, pal_litOVERRIDE);//Forcibly set permLit, overriding it's current setting
7508 cheats_execute_light = false;
7509 }
7510
7511
3/4
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 3776 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1888 times.
5664 if(action!=climbcovertop&&action!=climbcoverbottom)
7512 {
7513 1888 climb_cover_x=-1000;
7514 1888 climb_cover_y=-1000;
7515 1888 }
7516
7517
1/2
✓ Branch 0 taken 5664 times.
✗ Branch 1 not taken.
5664 if(mirror_portal)
7518 {
7519 mirror_portal->animate(0);
7520 if(abs(x - mirror_portal->x) < 12
7521 && abs(y - mirror_portal->y) < 12)
7522 {
7523 if(can_mirror_portal)
7524 {
7525 //Store some values to restore if 'warp fails'
7526 int32_t tLastEntrance = lastentrance,
7527 tLastEntranceDMap = lastentrance_dmap,
7528 tContScr = game->get_continue_scrn(),
7529 tContDMap = game->get_continue_dmap();
7530 int32_t sourcescr = currscr, sourcedmap = currdmap;
7531 zfix tx = x, ty = y, tz = z;
7532 x = mirror_portal->x;
7533 y = mirror_portal->y;
7534
7535 int32_t weff = mirror_portal->weffect,
7536 wsfx = mirror_portal->wsfx;
7537
7538 FFCore.warp_player(wtIWARP, mirror_portal->destdmap, mirror_portal->destscr,
7539 -1, -1, weff, wsfx, 0, -1);
7540
7541 if(mirrorBonk()) //Invalid landing, warp back!
7542 {
7543 action = none; FFCore.setHeroAction(none);
7544 lastentrance = tLastEntrance;
7545 lastentrance_dmap = tLastEntranceDMap;
7546 game->set_continue_scrn(tContScr);
7547 game->set_continue_dmap(tContDMap);
7548 x = tx;
7549 y = ty;
7550 z = tz;
7551 FFCore.warp_player(wtIWARP, sourcedmap, sourcescr, -1, -1, weff,
7552 wsfx, 0, -1);
7553 can_mirror_portal = false;
7554 }
7555 else game->clear_portal(); //Remove portal once used
7556 }
7557 }
7558 else can_mirror_portal = true;
7559 }
7560
7561
3/4
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 3776 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1888 times.
5664 if(z<=8&&fakez<=8)
7562 {
7563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if (get_bit(quest_rules, qr_GRASS_SENSITIVE))
7564 {
7565 bool g1 = isGrassType(COMBOTYPE(x+4,y+15)), g2 = isGrassType(COMBOTYPE(x+11,y+15)), g3 = isGrassType(COMBOTYPE(x+4,y+9)), g4 = isGrassType(COMBOTYPE(x+11,y+9));
7566 if(get_bit(quest_rules, qr_BUSHESONLAYERS1AND2))
7567 {
7568 g1 = g1 || isGrassType(COMBOTYPEL(1,x+4,y+15)) || isGrassType(COMBOTYPEL(2,x+4,y+15));
7569 g2 = g2 || isGrassType(COMBOTYPEL(1,x+11,y+15)) || isGrassType(COMBOTYPEL(2,x+11,y+15));
7570 g3 = g3 || isGrassType(COMBOTYPEL(1,x+4,y+9)) || isGrassType(COMBOTYPEL(2,x+4,y+9));
7571 g4 = g4 || isGrassType(COMBOTYPEL(1,x+11,y+9)) || isGrassType(COMBOTYPEL(2,x+11,y+9));
7572 }
7573 if(g1 && g2 && g3 && g4)
7574 {
7575 if(decorations.idCount(dTALLGRASS)==0)
7576 {
7577 decorations.add(new dTallGrass(x, y, dTALLGRASS, 0));
7578 }
7579 int32_t thesfx = combobuf[MAPCOMBO(x+8,y+12)].attribytes[3];
7580 if ( thesfx > 0 && !sfx_allocated(thesfx) && action==walking )
7581 sfx(thesfx,pan((int32_t)x));
7582 }
7583 }
7584 else
7585 {
7586 1888 bool g1 = isGrassType(COMBOTYPE(x,y+15)), g2 = isGrassType(COMBOTYPE(x+15,y+15));
7587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(get_bit(quest_rules, qr_BUSHESONLAYERS1AND2))
7588 {
7589 g1 = g1 || isGrassType(COMBOTYPEL(1,x,y+15)) || isGrassType(COMBOTYPEL(2,x,y+15));
7590 g2 = g2 || isGrassType(COMBOTYPEL(1,x+15,y+15)) || isGrassType(COMBOTYPEL(2,x+15,y+15));
7591 }
7592
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if(g1 && g2)
7593 {
7594 if(decorations.idCount(dTALLGRASS)==0)
7595 {
7596 decorations.add(new dTallGrass(x, y, dTALLGRASS, 0));
7597 }
7598 int32_t thesfx = combobuf[MAPCOMBO(x+8,y+15)].attribytes[3];
7599 if ( thesfx > 0 && !sfx_allocated(thesfx) && action==walking )
7600 sfx(thesfx,pan((int32_t)x));
7601 }
7602 }
7603 1888 }
7604
7605
2/2
✓ Branch 0 taken 3776 times.
✓ Branch 1 taken 1888 times.
5664 if (get_bit(quest_rules, qr_SHALLOW_SENSITIVE))
7606 {
7607
1/26
✗ Branch 0 not taken.
✓ Branch 1 taken 3776 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
3776 if (z == 0 && fakez == 0 && action != swimming && action != isdiving && action != drowning && action!=lavadrowning && action!=sidedrowning && action!=rafting && action != falling && !IsSideSwim() && !(ladderx+laddery) && !pull_hero && !toogam)
7608 {
7609 if (iswaterex(FFORCOMBO(x+11,y+15), currmap, currscr, -1, x+11,y+15, false, false, true, true)
7610 && iswaterex(FFORCOMBO(x+4,y+15), currmap, currscr, -1, x+4,y+15, false, false, true, true)
7611 && iswaterex(FFORCOMBO(x+11,y+9), currmap, currscr, -1, x+11,y+9, false, false, true, true)
7612 && iswaterex(FFORCOMBO(x+4,y+9), currmap, currscr, -1, x+4,y+9, false, false, true, true))
7613 {
7614 if(decorations.idCount(dRIPPLES)==0)
7615 {
7616 decorations.add(new dRipples(x, y, dRIPPLES, 0));
7617 }
7618 int32_t watercheck = iswaterex(FFORCOMBO(x.getInt()+7.5,y.getInt()+12), currmap, currscr, -1, x.getInt()+7.5,y.getInt()+12, false, false, true, true);
7619 if (combobuf[watercheck].usrflags&cflag2)
7620 {
7621 if (!(current_item(combobuf[watercheck].attribytes[2]) > 0 && current_item(combobuf[watercheck].attribytes[2]) >= combobuf[watercheck].attribytes[3]))
7622 {
7623 onpassivedmg = true;
7624 if (!damageovertimeclk)
7625 {
7626 int32_t curhp = game->get_life();
7627 if (combobuf[watercheck].usrflags&cflag5) game->set_life(vbound(game->get_life()+ringpower(combobuf[watercheck].attributes[1]/10000L), 0, game->get_maxlife())); //Affected by rings
7628 else game->set_life(vbound(game->get_life()+combobuf[watercheck].attributes[1]/10000L, 0, game->get_maxlife()));
7629 if ((combobuf[watercheck].attributes[2]/10000L) && (game->get_life() != curhp || !(combobuf[watercheck].usrflags&cflag6))) sfx(combobuf[watercheck].attributes[2]/10000L);
7630 if (game->get_life() < curhp && combobuf[watercheck].usrflags&cflag7)
7631 {
7632 hclk = 48;
7633 hitdir = -1;
7634 action = gothit; FFCore.setHeroAction(gothit);
7635 }
7636 }
7637 if (combobuf[watercheck].attribytes[1] > 0)
7638 {
7639 if (!damageovertimeclk || damageovertimeclk > combobuf[watercheck].attribytes[1]) damageovertimeclk = combobuf[watercheck].attribytes[1];
7640 else --damageovertimeclk;
7641 }
7642 else damageovertimeclk = 0;
7643 }
7644 else damageovertimeclk = 0;
7645 }
7646 else damageovertimeclk = 0;
7647 int32_t thesfx = combobuf[watercheck].attribytes[0];
7648 if ( thesfx > 0 && !sfx_allocated(thesfx) && action==walking )
7649 sfx(thesfx,pan((int32_t)x));
7650 }
7651 }
7652 3776 }
7653 else
7654 {
7655
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1888 times.
✗ Branch 7 not taken.
1888 if((COMBOTYPE(x,y+15)==cSHALLOWWATER)&&(COMBOTYPE(x+15,y+15)==cSHALLOWWATER) && z==0 && fakez==0)
7656 {
7657 if(decorations.idCount(dRIPPLES)==0)
7658 {
7659 decorations.add(new dRipples(x, y, dRIPPLES, 0));
7660 }
7661 int32_t watercheck = FFORCOMBO(x+7.5,y.getInt()+15);
7662 if (combobuf[watercheck].usrflags&cflag2)
7663 {
7664 if (!(current_item(combobuf[watercheck].attribytes[2]) > 0 && current_item(combobuf[watercheck].attribytes[2]) >= combobuf[watercheck].attribytes[3]))
7665 {
7666 onpassivedmg = true;
7667 if (!damageovertimeclk)
7668 {
7669 int32_t curhp = game->get_life();
7670 if (combobuf[watercheck].usrflags&cflag5) game->set_life(vbound(game->get_life()+ringpower(combobuf[watercheck].attributes[1]/10000L), 0, game->get_maxlife())); //Affected by rings
7671 else game->set_life(vbound(game->get_life()+(combobuf[watercheck].attributes[1]/10000L), 0, game->get_maxlife()));
7672 if ((combobuf[watercheck].attributes[2]/10000L) && (game->get_life() != curhp || !(combobuf[watercheck].usrflags&cflag6))) sfx(combobuf[watercheck].attributes[2]/10000L);
7673 }
7674 if (combobuf[watercheck].attribytes[1] > 0)
7675 {
7676 if (!damageovertimeclk || damageovertimeclk > combobuf[watercheck].attribytes[1]) damageovertimeclk = combobuf[watercheck].attribytes[1];
7677 else --damageovertimeclk;
7678 }
7679 else damageovertimeclk = 0;
7680 }
7681 else damageovertimeclk = 0;
7682 }
7683 else damageovertimeclk = 0;
7684 int32_t thesfx = combobuf[watercheck].attribytes[0];
7685 if ( thesfx > 0 && !sfx_allocated(thesfx) && action==walking )
7686 sfx(thesfx,pan((int32_t)x));
7687 }
7688 }
7689
7690
1/2
✓ Branch 0 taken 5664 times.
✗ Branch 1 not taken.
5664 if(stomping)
7691 stomping = false;
7692
7693
1/2
✓ Branch 0 taken 5664 times.
✗ Branch 1 not taken.
5664 if(getOnSideviewLadder())
7694 {
7695 if(!canSideviewLadder() || jumping<0 || fall!=0 || fakefall!=0)
7696 {
7697 setOnSideviewLadder(false);
7698 }
7699 else if(CANFORCEFACEUP)
7700 {
7701 setDir(up);
7702 }
7703 }
7704
7705
5/8
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 3776 times.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1888 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1888 times.
5664 if(action!=inwind && action!=drowning && action!=lavadrowning && action!= sidedrowning)
7706 {
7707
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(!get_bit(quest_rules,qr_OLD_CHEST_COLLISION))
7708 {
7709 checkchest(cCHEST);
7710 checkchest(cLOCKEDCHEST);
7711 checkchest(cBOSSCHEST);
7712 }
7713
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(!get_bit(quest_rules, qr_OLD_LOCKBLOCK_COLLISION))
7714 {
7715 checkchest(cLOCKBLOCK);
7716 checkchest(cBOSSLOCKBLOCK);
7717 }
7718 1888 }
7719 5664 checksigns();
7720 5664 checkgenpush();
7721
7722
2/2
✓ Branch 0 taken 3776 times.
✓ Branch 1 taken 1888 times.
5664 if(isStanding())
7723 {
7724
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(extra_jump_count > 0)
7725 extra_jump_count = 0;
7726 1888 }
7727
1/2
✓ Branch 0 taken 5664 times.
✗ Branch 1 not taken.
5664 if(can_use_item(itype_hoverboots,i_hoverboots))
7728 {
7729 int32_t hoverid = current_item_id(itype_hoverboots);
7730 if(!(itemsbuf[hoverid].flags & ITEM_FLAG1))
7731 {
7732 if(hoverclk < 0) hoverclk = 0;
7733 hoverflags &= ~HOV_OUT;
7734 }
7735 }
7736 5664 bool platformfell2 = false;
7737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5664 times.
5664 if(sideview_mode()) // Sideview gravity
7738 {
7739 //Handle falling through a platform
7740 bool platformfell = false;
7741 if (on_sideview_solid_oldpos(x,y,old_x,old_y,true,3) && !on_sideview_solid_oldpos(x,y,old_x,old_y,false,3))
7742 {
7743 if (!(!on_sideview_slope(Hero.x, Hero.y,Hero.old_x,Hero.old_y) && (on_sideview_slope(Hero.x,Hero.y+1,Hero.old_x,Hero.old_y) || on_sideview_slope(Hero.x, Hero.y + 2, Hero.old_x, Hero.old_y)) && Down())) platformfell = true;
7744 y+=1; //Fall down a pixel instantly, through the platform.
7745 if(fall < 0) fall = 0;
7746 if(jumping < 0) jumping = 0;
7747 platformfell2 = true;
7748 }
7749 //Unless using old collision, run this check BEFORE moving Hero, to prevent clipping into the ceiling.
7750 if(!get_bit(quest_rules, qr_OLD_SIDEVIEW_CEILING_COLLISON))
7751 {
7752 if(fall < 0 && (_walkflag(x+4,y+((bigHitbox||!diagonalMovement)?(fall/100):(fall/100)+8),1,SWITCHBLOCK_STATE) || _walkflag(x+12,y+((bigHitbox||!diagonalMovement)?(fall/100):(fall/100)+8),1,SWITCHBLOCK_STATE)
7753 || ((y+(fall/100)<=0) &&
7754 // Extra checks if Smart Screen Scrolling is enabled
7755 (nextcombo_wf(up) || ((get_bit(quest_rules, qr_SMARTSCREENSCROLL)&&(!(tmpscr->flags&fMAZE)) &&
7756 !(tmpscr->flags2&wfUP)) && (nextcombo_solid(up)))))))
7757 {
7758 fall = jumping = 0; // Bumped his head
7759 if(get_bit(quest_rules,qr_OLD_SIDEVIEW_LANDING_CODE))
7760 y -= y.getInt()%8; //fix coords
7761 // ... maybe on spikes //this is the change from 2.50.1RC3 that Saffith made, that breaks some old quests. -Z
7762 if ( !get_bit(quest_rules, qr_OLDSIDEVIEWSPIKES) ) //fix for older sideview quests -Z
7763 {
7764 checkdamagecombos(x+4, x+12, y-1, y-1);
7765 }
7766 }
7767 }
7768 // Fall, unless on a ladder, sideview ladder, rafting, using the hookshot, drowning, sideswimming or cheating.
7769 if(!(toogam && Up()) && !drownclk && action!=rafting && !IsSideSwim() && !pull_hero && !((ladderx || laddery) && fall>0) && !getOnSideviewLadder())
7770 {
7771 int32_t ydiff = fall/(spins && fall<0 ? 200:100);
7772 //zprint2("ydif is: %d\n", ydiff);
7773 //zprint2("ydif is: %d\n", (int32_t)fall);
7774 falling_oldy = y; // Stomp Boots-related variable
7775 if(fall > 0 && (checkSVLadderPlatform(x+4,y+ydiff+15)||checkSVLadderPlatform(x+12,y+ydiff+15)) && (((y.getInt()+ydiff+15)&0xF0)!=((y.getInt()+15)&0xF0)) && !platform_fallthrough())
7776 {
7777 ydiff -= (y.getInt()+ydiff)%16;
7778 }
7779 if(ydiff && !get_bit(quest_rules,qr_OLD_SIDEVIEW_LANDING_CODE))
7780 {
7781 if(ydiff > 0)
7782 {
7783 for(auto q = 0; q < ydiff; ++q)
7784 {
7785 if(on_sideview_solid_oldpos(x,y+q,old_x,old_y))
7786 {
7787 ydiff = q;
7788 break;
7789 }
7790 }
7791 }
7792 else if(ydiff < 0)
7793 {
7794 for(auto q = 0; q > ydiff; --q)
7795 {
7796 if(_walkflag(x+4,y+(bigHitbox?0:8)+q-1,1)
7797 || _walkflag(x+12,y+(bigHitbox?0:8)+q,1))
7798 {
7799 ydiff = q;
7800 break;
7801 }
7802 }
7803 }
7804 }
7805 y+=ydiff;
7806 hs_starty+=ydiff;
7807
7808 for(int32_t j=0; j<chainlinks.Count(); j++)
7809 {
7810 chainlinks.spr(j)->y+=ydiff;
7811 }
7812
7813 if(Lwpns.idFirst(wHookshot)>-1)
7814 {
7815 Lwpns.spr(Lwpns.idFirst(wHookshot))->y+=ydiff;
7816 }
7817
7818 if(Lwpns.idFirst(wHSHandle)>-1)
7819 {
7820 Lwpns.spr(Lwpns.idFirst(wHSHandle))->y+=ydiff;
7821 }
7822 }
7823 else if(IsSideSwim() && action != sidewaterhold1 && action != sidewaterhold2 && action != sideswimcasting && action != sideswimfreeze)
7824 {
7825 fall = hoverclk = jumping = 0;
7826 inair = false;
7827 hoverflags = 0;
7828 if(!DrunkUp() && !DrunkDown() && !DrunkLeft() && !DrunkRight() && !autostep)
7829 {
7830 WalkflagInfo info;
7831 if (game->get_watergrav()<0)
7832 {
7833 info = walkflag(x,y+8-(bigHitbox*8)-2,2,up);
7834 execute(info);
7835 }
7836 else
7837 {
7838 info = walkflag(x,y+15+2,2,down);
7839 execute(info);
7840 }
7841 if(!info.isUnwalkable() && (game->get_watergrav() > 0 || iswaterex(MAPCOMBO(x,y+8-(bigHitbox*8)-2), currmap, currscr, -1, x, y+8-(bigHitbox*8)-2, true, false))) y+=(game->get_watergrav()/10000.0);
7842 }
7843 }
7844 // Stop hovering/falling if you land on something.
7845 bool needFall = false;
7846 if((on_sideview_solid_oldpos(x,y,old_x,old_y) || getOnSideviewLadder()) && !(pull_hero && dir==down) && action!=rafting && !platformfell2)
7847 {
7848 stop_item_sfx(itype_hoverboots);
7849 if(get_bit(quest_rules,qr_OLD_SIDEVIEW_LANDING_CODE)
7850 && !getOnSideviewLadder()
7851 && (fall > 0 || get_bit(quest_rules, qr_OLD_SIDEVIEW_CEILING_COLLISON)))
7852 y-=(int32_t)y%8; //fix position
7853 fall = hoverclk = jumping = 0;
7854 inair = false;
7855 hoverflags = 0;
7856
7857 if(y>=160 && currscr>=0x70 && !(tmpscr->flags2&wfDOWN)) // Landed on the bottommost screen.
7858 y = 160;
7859 }
7860 // Stop hovering if you press down.
7861 else if((hoverclk>0 || ladderx || laddery) && DrunkDown())
7862 {
7863 stop_item_sfx(itype_hoverboots);
7864 hoverclk = -hoverclk;
7865 reset_ladder();
7866 fall = (zinit.gravity2 / 100);
7867 inair = false;
7868 }
7869 else if (hoverclk < 1 && !inair && fall == 0 && !platformfell)
7870 {
7871 zfix my = y + (zinit.gravity2/100);
7872 needFall = true;
7873 for (zfix ty = y+1; ty < my; ++ty)
7874 {
7875 //if (on_sideview_solid_oldpos(x, ty,old_x,old_y, false, 1)) break;
7876 if (on_sideview_solid_oldpos(x, ty,old_x,old_y, false, 0))
7877 {
7878 y = ty;
7879 if (check_new_slope(x, ty + 1, 16, 16, old_x, old_y, false) < 0)
7880 {
7881 if(!slopeid)
7882 slopeid = get_new_slope(x, ty + 1, 16, 16, old_x, old_y).get_info().slope();
7883 onplatid = 5;
7884 }
7885 needFall = false;
7886 break;
7887 }
7888 }
7889 }
7890 else needFall = true;
7891 // Continue falling.
7892
7893 if(fall <= (int32_t)zinit.terminalv && needFall)
7894 {
7895 inair = true;
7896 if(fall != 0 || hoverclk>0)
7897 jumping++;
7898
7899 // Bump head if: hit a solid combo from beneath, or hit a solid combo in the screen above this one.
7900 if(get_bit(quest_rules, qr_OLD_SIDEVIEW_CEILING_COLLISON))
7901 {
7902 if((_walkflag(x+4,y-(bigHitbox?9:1),0,SWITCHBLOCK_STATE)
7903 || (y<=(bigHitbox?9:1) &&
7904 // Extra checks if Smart Screen Scrolling is enabled
7905 (nextcombo_wf(up) || ((get_bit(quest_rules, qr_SMARTSCREENSCROLL)&&(!(tmpscr->flags&fMAZE)) &&
7906 !(tmpscr->flags2&wfUP)) && (nextcombo_solid(up))))))
7907 && fall < 0)
7908 {
7909 fall = jumping = 0; // Bumped his head
7910
7911 // ... maybe on spikes //this is the change from 2.50.1RC3 that Saffith made, that breaks some old quests. -Z
7912 if ( !get_bit(quest_rules, qr_OLDSIDEVIEWSPIKES) ) //fix for older sideview quests -Z
7913 {
7914 checkdamagecombos(x+4, x+12, y-1, y-1);
7915 }
7916 }
7917 }
7918 else
7919 {
7920 if((_walkflag(x+4,y+((bigHitbox||!diagonalMovement)?-1:7),1,SWITCHBLOCK_STATE) || _walkflag(x+12,y+((bigHitbox||!diagonalMovement)?-1:7),1,SWITCHBLOCK_STATE)
7921 || ((y<=0) &&
7922 // Extra checks if Smart Screen Scrolling is enabled
7923 (nextcombo_wf(up) || ((get_bit(quest_rules, qr_SMARTSCREENSCROLL)&&(!(tmpscr->flags&fMAZE)) &&
7924 !(tmpscr->flags2&wfUP)) && (nextcombo_solid(up))))))
7925 && fall < 0)
7926 {
7927 fall = jumping = 0; // Bumped his head
7928 y -= y.getInt()%8; //fix coords
7929 // ... maybe on spikes //this is the change from 2.50.1RC3 that Saffith made, that breaks some old quests. -Z
7930 if ( !get_bit(quest_rules, qr_OLDSIDEVIEWSPIKES) ) //fix for older sideview quests -Z
7931 {
7932 checkdamagecombos(x+4, x+12, y-1, y-1);
7933 }
7934 }
7935 }
7936
7937 if(hoverclk > 0)
7938 {
7939 if(hoverclk > 0 && !(hoverflags&HOV_INF))
7940 {
7941 --hoverclk;
7942 }
7943
7944 if(!hoverclk && !ladderx && !laddery)
7945 {
7946 fall += (zinit.gravity2 / 100);
7947 hoverflags |= HOV_OUT | HOV_PITFALL_OUT;
7948 }
7949 }
7950 else if(fall+int32_t((zinit.gravity2 / 100)) > 0 && fall<=0 && can_use_item(itype_hoverboots,i_hoverboots) && !ladderx && !laddery && !(hoverflags & HOV_OUT))
7951 {
7952 int32_t itemid = current_item_id(itype_hoverboots);
7953 if(hoverclk < 0)
7954 hoverclk = -hoverclk;
7955 else
7956 {
7957 fall = jumping = 0;
7958 if(itemsbuf[itemid].misc1)
7959 hoverclk = itemsbuf[itemid].misc1;
7960 else
7961 {
7962 hoverclk = 1;
7963 hoverflags |= HOV_INF;
7964 }
7965
7966
7967 sfx(itemsbuf[itemid].usesound,pan(x.getInt()));
7968 }
7969 if(itemsbuf[itemid].wpn)
7970 decorations.add(new dHover(x, y, dHOVER, 0));
7971 }
7972 else if(!ladderx && !laddery && !getOnSideviewLadder() && !IsSideSwim())
7973 {
7974 fall += (zinit.gravity2 / 100);
7975
7976 }
7977 }
7978 }
7979 else // Topdown gravity
7980 {
7981
3/4
✓ Branch 0 taken 3776 times.
✓ Branch 1 taken 1888 times.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
5664 if (!(moveflags & FLAG_NO_FAKE_Z)) fakez-=fakefall/(spins && fakefall>0 ? 200:100);
7982
3/4
✓ Branch 0 taken 3776 times.
✓ Branch 1 taken 1888 times.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
5664 if (!(moveflags & FLAG_NO_REAL_Z)) z-=fall/(spins && fall>0 ? 200:100);
7983
4/4
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 3776 times.
✓ Branch 2 taken 3776 times.
✓ Branch 3 taken 5664 times.
5664 if(z>0||fakez>0)
7984 {
7985
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7552 switch(action)
7986 {
7987 case swimming:
7988 {
7989 diveclk=0;
7990 action=walking; FFCore.setHeroAction(walking);
7991
7992 break;
7993 }
7994 case waterhold1:
7995 {
7996 action=landhold1; FFCore.setHeroAction(landhold1);
7997 break;
7998 }
7999
8000 case waterhold2:
8001 {
8002 action=landhold2; FFCore.setHeroAction(landhold2);
8003 break;
8004 }
8005
8006 default:
8007 break;
8008 }
8009 }
8010
8011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5664 times.
5664 for(int32_t j=0; j<chainlinks.Count(); j++)
8012 {
8013 chainlinks.spr(j)->z=z;
8014 chainlinks.spr(j)->fakez=fakez;
8015 }
8016
8017
1/2
✓ Branch 0 taken 5664 times.
✗ Branch 1 not taken.
5664 if(Lwpns.idFirst(wHookshot)>-1)
8018 {
8019 Lwpns.spr(Lwpns.idFirst(wHookshot))->z=z;
8020 Lwpns.spr(Lwpns.idFirst(wHookshot))->fakez=fakez;
8021 }
8022
8023
1/2
✓ Branch 0 taken 5664 times.
✗ Branch 1 not taken.
5664 if(Lwpns.idFirst(wHSHandle)>-1)
8024 {
8025 Lwpns.spr(Lwpns.idFirst(wHSHandle))->z=z;
8026 Lwpns.spr(Lwpns.idFirst(wHSHandle))->fakez=fakez;
8027 }
8028
8029
3/4
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 3776 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1888 times.
5664 if(z<=0&&!(moveflags & FLAG_NO_REAL_Z))
8030 {
8031
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if (fakez <= 0 || (moveflags & FLAG_NO_FAKE_Z))
8032 {
8033
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(fall > 0)
8034 {
8035 if((iswaterex(MAPCOMBO(x,y+8), currmap, currscr, -1, x, y+8, true, false) && ladderx<=0 && laddery<=0) || COMBOTYPE(x,y+8)==cSHALLOWWATER)
8036 sfx(WAV_ZN1SPLASH,x.getInt());
8037
8038 stomping = true;
8039 }
8040 1888 }
8041 1888 z = fall = 0;
8042
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if (fakez <= 0 || (moveflags & FLAG_NO_FAKE_Z))
8043 {
8044 1888 jumping = 0;
8045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(check_pitslide(true) == -1)
8046 {
8047 1888 hoverclk = 0;
8048 1888 hoverflags = 0;
8049 1888 }
8050 else if(hoverclk > 0 && !(hoverflags&HOV_INF))
8051 {
8052 if(!--hoverclk)
8053 {
8054 hoverflags |= HOV_OUT | HOV_PITFALL_OUT;
8055 }
8056 }
8057 1888 }
8058 1888 }
8059
3/4
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 3776 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1888 times.
5664 if(fakez<=0&&!(moveflags & FLAG_NO_FAKE_Z))
8060 {
8061
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if (z <= 0 || (moveflags & FLAG_NO_REAL_Z))
8062 {
8063
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(fakefall > 0)
8064 {
8065 if((iswaterex(MAPCOMBO(x,y+8), currmap, currscr, -1, x, y+8, true, false) && ladderx<=0 && laddery<=0) || COMBOTYPE(x,y+8)==cSHALLOWWATER)
8066 sfx(WAV_ZN1SPLASH,x.getInt());
8067
8068 stomping = true;
8069 }
8070 1888 }
8071 1888 fakez = fakefall = 0;
8072
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if (z <= 0 || (moveflags & FLAG_NO_REAL_Z))
8073 {
8074 1888 jumping = 0;
8075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(check_pitslide(true) == -1)
8076 {
8077 1888 hoverclk = 0;
8078 1888 hoverflags = 0;
8079 1888 }
8080 else if(hoverclk > 0 && !(hoverflags&HOV_INF))
8081 {
8082 if(!--hoverclk)
8083 {
8084 hoverflags |= HOV_OUT | HOV_PITFALL_OUT;
8085 }
8086 }
8087 1888 }
8088 1888 }
8089
7/10
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 3776 times.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1888 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1888 times.
✓ Branch 7 taken 1888 times.
✓ Branch 8 taken 1888 times.
✗ Branch 9 not taken.
5664 if(fall <= (int32_t)zinit.terminalv && !(moveflags & FLAG_NO_REAL_Z) && z>0 || fakefall <= (int32_t)zinit.terminalv && !(moveflags & FLAG_NO_FAKE_Z) && fakez > 0)
8090 {
8091
0/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3776 if(fall != 0 || fakefall != 0 || hoverclk>0)
8092 jumping++;
8093
8094 if(hoverclk > 0)
8095 {
8096 if(hoverclk > 0 && !(hoverflags&HOV_INF))
8097 {
8098 --hoverclk;
8099 }
8100
8101 if(!hoverclk)
8102 {
8103 if (fall <= (int32_t)zinit.terminalv && !(moveflags & FLAG_NO_REAL_Z) && z > 0) fall += (zinit.gravity2 / 100);
8104 if (fakefall <= (int32_t)zinit.terminalv && !(moveflags & FLAG_NO_FAKE_Z) && fakez > 0) fakefall += (zinit.gravity2 / 100);
8105 hoverflags |= HOV_OUT | HOV_PITFALL_OUT;
8106 }
8107 }
8108 else if(((fall+(int32_t)(zinit.gravity2 / 100) > 0 && fall<=0 && !(moveflags & FLAG_NO_REAL_Z) && z > 0) || (fakefall+(int32_t)(zinit.gravity2 / 100) > 0 && fakefall<=0 && !(moveflags & FLAG_NO_FAKE_Z) && fakez > 0)) && can_use_item(itype_hoverboots,i_hoverboots) && !(hoverflags & HOV_OUT))
8109 {
8110 if(hoverclk < 0)
8111 hoverclk = -hoverclk;
8112 else
8113 {
8114 fall = 0;
8115 fakefall = 0;
8116 int32_t itemid = current_item_id(itype_hoverboots);
8117 if(itemsbuf[itemid].misc1)
8118 hoverclk = itemsbuf[itemid].misc1;
8119 else
8120 {
8121 hoverclk = 1;
8122 hoverflags |= HOV_INF;
8123 }
8124 sfx(itemsbuf[current_item_id(itype_hoverboots)].usesound,pan(x.getInt()));
8125 }
8126 decorations.add(new dHover(x, y, dHOVER, 0));
8127 }
8128 else
8129 {
8130 if (fall <= (int32_t)zinit.terminalv && !(moveflags & FLAG_NO_REAL_Z) && z > 0) fall += (zinit.gravity2 / 100);
8131 if (fakefall <= (int32_t)zinit.terminalv && !(moveflags & FLAG_NO_FAKE_Z) && fakez > 0) fakefall += (zinit.gravity2 / 100);
8132 }
8133 }
8134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if (fakez<0) fakez = 0;
8135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if (z<0) z = 0;
8136 }
8137
8138
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(drunkclk)
8139 {
8140 --drunkclk;
8141 }
8142
8143
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(lstunclock > 0)
8144 {
8145 // also cancel Hero's attack
8146 attackclk = 0;
8147
8148 if( FFCore.getHeroAction() != stunned )
8149 {
8150 tempaction=action; //update so future checks won't do this
8151 //action=freeze; //setting this makes the player invincible while stunned -V
8152 FFCore.setHeroAction(stunned);
8153 }
8154 --lstunclock;
8155 }
8156 //if the stun action is still set in FFCore, but he isn't stunned, then the timer reached 0
8157 //, so we unfreeze him here, and return him to the action that he had when he was stunned.
8158
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if ( FFCore.getHeroAction() == stunned && !lstunclock )
8159 {
8160 action=tempaction; FFCore.setHeroAction(tempaction);
8161 //zprint("Unfreezing hero to action: %d\n", (int32_t)tempaction);
8162 //action=none; FFCore.setHeroAction(none);
8163 }
8164
8165
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if( lbunnyclock > 0 )
8166 {
8167 --lbunnyclock;
8168 }
8169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(DMaps[currdmap].flags&dmfBUNNYIFNOPEARL)
8170 {
8171 int32_t itemid = current_item_id(itype_pearl);
8172 if(itemid > -1)
8173 {
8174 if(lbunnyclock == -1) //cure dmap-caused bunny effect
8175 lbunnyclock = 0;
8176 }
8177 else if(lbunnyclock > -1) //No pearl, force into bunny mode
8178 {
8179 lbunnyclock = -1;
8180 }
8181 }
8182
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 else if(lbunnyclock == -1) //dmap-caused bunny effect
8183 {
8184 lbunnyclock = 0;
8185 }
8186
8187
6/16
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1888 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1888 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 1888 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1888 times.
1888 if(!is_on_conveyor && !(diagonalMovement||NO_GRIDLOCK) && (fall==0 || fakefall==0 || z>0 || fakez>0) && charging==0 && spins<=5
8188
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 && action != gothit)
8189 {
8190
2/3
✓ Branch 0 taken 771 times.
✓ Branch 1 taken 1117 times.
✗ Branch 2 not taken.
1888 switch(dir)
8191 {
8192 case up:
8193 case down:
8194 771 x=(x.getInt()+4)&0xFFF8;
8195 771 break;
8196
8197 case left:
8198 case right:
8199 1117 y=(y.getInt()+4)&0xFFF8;
8200 1117 break;
8201 }
8202 1888 }
8203
8204
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if((watch==true) && clockclk)
8205 {
8206 --clockclk;
8207
8208 if(!clockclk)
8209 {
8210 if(cheat_superman==false)
8211 {
8212 setClock(false);
8213 }
8214
8215 watch=false;
8216
8217 for(int32_t i=0; i<eMAXGUYS; i++)
8218 {
8219 for(int32_t zoras=0; zoras<clock_zoras[i]; zoras++)
8220 {
8221 addenemy(0,0,i,0);
8222 }
8223 }
8224 }
8225 }
8226
8227
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1888 times.
1888 if(hookshot_frozen || switch_hooked)
8228 {
8229 if(hookshot_used || switch_hooked)
8230 {
8231 if (IsSideSwim()) {action=sideswimfreeze; FFCore.setHeroAction(sideswimfreeze);}
8232 else {action=freeze; FFCore.setHeroAction(freeze);} //could be LA_HOOKSHOT for FFCore. -Z
8233
8234 if(pull_hero || switch_hooked)
8235 {
8236 if(hs_switcher || switch_hooked)
8237 {
8238 hs_fix = false;
8239 if(switchhookclk)
8240 {
8241 --switchhookclk;
8242 if(switchhookclk==switchhookmaxtime/2) //Perform swaps
8243 {
8244 if(switchhook_cost_item > -1 && !checkmagiccost(switchhook_cost_item))
8245 reset_hookshot();
8246 else
8247 {
8248 weapon *w = (weapon*)Lwpns.spr(Lwpns.idFirst(wHookshot)),
8249 *hw = (weapon*)Lwpns.spr(Lwpns.idFirst(wHSHandle));
8250
8251 if(hooked_combopos > -1) //Switching combos
8252 {
8253 uint16_t targpos = hooked_combopos, plpos = COMBOPOS(x+8,y+8);
8254 if(targpos < 176 && plpos < 176 && hooked_layerbits)
8255 {
8256 int32_t max_layer = get_bit(quest_rules, qr_HOOKSHOTALLLAYER) ? 6 : (get_bit(quest_rules, qr_HOOKSHOTLAYERFIX) ? 2 : 0);
8257 for(int q = max_layer; q > -1; --q)
8258 {
8259 if(!(hooked_layerbits & (1<<q)))
8260 continue; //non-switching layer
8261 mapscr* scr = FFCore.tempScreens[q];
8262 newcombo const& cmb = combobuf[scr->data[targpos]];
8263 int32_t srcfl = scr->sflag[targpos];
8264 newcombo const& comb2 = combobuf[scr->data[plpos]];
8265 int32_t c = scr->data[plpos], cs = scr->cset[plpos], fl = scr->sflag[plpos];
8266 //{Check push status
8267 bool isFakePush = false;
8268 if(cmb.type == cSWITCHHOOK)
8269 {
8270 if(cmb.usrflags&cflag7) //counts as 'pushblock'
8271 isFakePush = true;
8272 }
8273 bool isPush = isFakePush;
8274 if(!isPush) switch(srcfl)
8275 {
8276 case mfPUSHUD: case mfPUSHUDNS: case mfPUSHUDINS:
8277 case mfPUSHLR: case mfPUSHLRNS: case mfPUSHLRINS:
8278 case mfPUSHU: case mfPUSHUNS: case mfPUSHUINS:
8279 case mfPUSHD: case mfPUSHDNS: case mfPUSHDINS:
8280 case mfPUSHL: case mfPUSHLNS: case mfPUSHLINS:
8281 case mfPUSHR: case mfPUSHRNS: case mfPUSHRINS:
8282 case mfPUSH4: case mfPUSH4NS: case mfPUSH4INS:
8283 isPush = true;
8284 }
8285 if(!isPush) switch(cmb.flag)
8286 {
8287 case mfPUSHUD: case mfPUSHUDNS: case mfPUSHUDINS:
8288 case mfPUSHLR: case mfPUSHLRNS: case mfPUSHLRINS:
8289 case mfPUSHU: case mfPUSHUNS: case mfPUSHUINS:
8290 case mfPUSHD: case mfPUSHDNS: case mfPUSHDINS:
8291 case mfPUSHL: case mfPUSHLNS: case mfPUSHLINS:
8292 case mfPUSHR: case mfPUSHRNS: case mfPUSHRINS:
8293 case mfPUSH4: case mfPUSH4NS: case mfPUSH4INS:
8294 isPush = true;
8295 }
8296 if(srcfl==mfPUSHED) isPush = false;
8297 //}
8298 if(cmb.type == cSWITCHHOOK) //custom flags and such
8299 {
8300 if(cmb.usrflags&cflag3) //Breaks on swap
8301 {
8302 int32_t it = -1;
8303 int32_t thedropset = -1;
8304 if(cmb.usrflags&cflag4) //drop item
8305 {
8306 if(cmb.usrflags&cflag5)
8307 it = cmb.attribytes[2];
8308 else
8309 {
8310 it = select_dropitem(cmb.attribytes[2]);
8311 thedropset = cmb.attribytes[2];
8312 }
8313 }
8314
8315 breakable* br = new breakable(x, y, zfix(0),
8316 cmb, scr->cset[targpos], it, thedropset, cmb.attribytes[2],
8317 cmb.attribytes[1] ? -1 : 0, cmb.attribytes[1], switchhookclk);
8318 br->switch_hooked = true;
8319 decorations.add(br);
8320 hooked_layerbits &= ~(0x101<<q); //this swap completed entirely
8321 hooked_undercombos[q] = -1;
8322
8323 if(cmb.usrflags&cflag6)
8324 {
8325 scr->data[targpos]++;
8326 }
8327 else
8328 {
8329 scr->data[targpos] = scr->undercombo;
8330 scr->cset[targpos] = scr->undercset;
8331 if(cmb.usrflags&cflag2)
8332 scr->sflag[targpos] = 0;
8333 }
8334 }
8335 else if(isPush)
8336 {
8337 //Simulate a block clicking into place
8338 movingblock mtemp;
8339 mtemp.clear();
8340 mtemp.set(COMBOX(plpos),COMBOY(plpos),scr->data[targpos],scr->cset[targpos],q,scr->sflag[targpos]);
8341 mtemp.dir = getPushDir(scr->sflag[targpos]);
8342 if(mtemp.dir < 0)
8343 mtemp.dir = getPushDir(cmb.flag);
8344 mtemp.clk = 1;
8345 if(isFakePush)
8346 mtemp.force_many = true;
8347 mtemp.animate(0);
8348 if((mtemp.bhole || mtemp.trigger)
8349 && (fl == mfBLOCKTRIGGER || fl == mfBLOCKHOLE
8350 || comb2.flag == mfBLOCKTRIGGER
8351 || comb2.flag == mfBLOCKHOLE))
8352 {
8353 scr->data[targpos] = scr->undercombo;
8354 scr->cset[targpos] = scr->undercset;
8355 scr->sflag[targpos] = 0;
8356 }
8357 else
8358 {
8359 scr->data[targpos] = c;
8360 scr->cset[targpos] = cs;
8361 if(cmb.usrflags&cflag2)
8362 scr->sflag[targpos] = fl;
8363 else
8364 scr->sflag[targpos] = 0;
8365 }
8366 }
8367 else
8368 {
8369 scr->data[plpos] = scr->data[targpos];
8370 scr->cset[plpos] = scr->cset[targpos];
8371 if(cmb.usrflags&cflag2)
8372 scr->sflag[plpos] = scr->sflag[targpos];
8373 scr->data[targpos] = c;
8374 scr->cset[targpos] = cs;
8375 if(cmb.usrflags&cflag2)
8376 scr->sflag[targpos] = fl;
8377 }
8378 }
8379 else if(isCuttableType(cmb.type)) //Break and drop effects
8380 {
8381 int32_t breakcs = scr->cset[targpos];
8382 if(isCuttableNextType(cmb.type)) //next instead of undercmb
8383 {
8384 scr->data[targpos]++;
8385 }
8386 else
8387 {
8388 scr->data[targpos] = scr->undercombo;
8389 scr->cset[targpos] = scr->undercset;
8390 scr->sflag[targpos] = 0;
8391 }
8392
8393 int32_t it = -1;
8394 int32_t thedropset = -1;
8395 if(isCuttableItemType(cmb.type)) //Drop an item
8396 {
8397 if ( (cmb.usrflags&cflag2) )
8398 {
8399 if(cmb.usrflags&cflag11)
8400 it = cmb.attribytes[1];
8401 else
8402 {
8403 it = select_dropitem(cmb.attribytes[1]);
8404 thedropset = cmb.attribytes[1];
8405 }
8406 }
8407 else
8408 {
8409 it = select_dropitem(12);
8410 thedropset = 12;
8411 }
8412 }
8413
8414 byte breaksfx = 0;
8415 if(get_bit(quest_rules,qr_MORESOUNDS)) //SFX
8416 {
8417 if (cmb.usrflags&cflag3)
8418 {
8419 breaksfx = cmb.attribytes[2];
8420 }
8421 else if(isBushType(cmb.type)
8422 || isFlowersType(cmb.type)
8423 || isGrassType(cmb.type))
8424 {
8425 breaksfx = QMisc.miscsfx[sfxBUSHGRASS];
8426 }
8427 }
8428
8429 //Clipping sprite
8430 int16_t decotype = (cmb.usrflags & cflag1) ?
8431 ((cmb.usrflags & cflag10)
8432 ? (cmb.attribytes[0])
8433 : (-1))
8434 : (0);
8435 if(decotype > 3) decotype = 0;
8436 if(!decotype)
8437 decotype = (isBushType(cmb.type) ? 1
8438 : (isFlowersType(cmb.type) ? 2
8439 : (isGrassType(cmb.type) ? 3
8440 : ((cmb.usrflags & cflag1) ? -1
8441 : -2))));
8442
8443 breakable* br = new breakable(x, y, zfix(0),
8444 cmb, breakcs, it, thedropset, breaksfx,
8445 decotype, cmb.attribytes[0], switchhookclk);
8446 br->switch_hooked = true;
8447 decorations.add(br);
8448 hooked_layerbits &= ~(0x101<<q); //this swap completed entirely
8449 hooked_undercombos[q] = -1;
8450 }
8451 else //Unknown type, just swap combos.
8452 {
8453 if(isPush)
8454 {
8455 //Simulate a block clicking into place
8456 movingblock mtemp;
8457 mtemp.clear();
8458 mtemp.set(COMBOX(plpos),COMBOY(plpos),scr->data[targpos],scr->cset[targpos],q,scr->sflag[targpos]);
8459 mtemp.dir = getPushDir(scr->sflag[targpos]);
8460 if(mtemp.dir < 0)
8461 mtemp.dir = getPushDir(cmb.flag);
8462 mtemp.clk = 1;
8463 mtemp.animate(0);
8464 if(mtemp.bhole || mtemp.trigger)
8465 {
8466 scr->data[targpos] = scr->undercombo;
8467 scr->cset[targpos] = scr->undercset;
8468 scr->sflag[targpos] = 0;
8469 }
8470 else
8471 {
8472 scr->data[targpos] = c;
8473 scr->cset[targpos] = cs;
8474 scr->sflag[targpos] = 0;
8475 }
8476 }
8477 else
8478 {
8479 scr->data[plpos] = scr->data[targpos];
8480 scr->cset[plpos] = scr->cset[targpos];
8481 scr->data[targpos] = c;
8482 scr->cset[targpos] = cs;
8483 }
8484 }
8485 }
8486 if(switchhook_cost_item > -1)
8487 paymagiccost(switchhook_cost_item);
8488 zfix tx = x, ty = y;
8489 //Position the player at the combo
8490 x = COMBOX(targpos);
8491 y = COMBOY(targpos);
8492 dir = oppositeDir[dir];
8493 if(w && hw)
8494 {
8495 //Calculate chain shift
8496 zfix dx = (x-tx);
8497 zfix dy = (y-ty);
8498 if(w->dir < 4)
8499 {
8500 if(w->dir & 2)
8501 dx = 0;
8502 else dy = 0;
8503 }
8504 //Position the hook head at the handle
8505 w->x = hw->x + dx;
8506 w->y = hw->y + dy;
8507 w->dir = oppositeDir[w->dir];
8508 w->doAutoRotate(true);
8509 byte hflip = (w->dir > 3 ? 3 : ((w->dir & 2) ? 1 : 2));
8510 w->flip ^= hflip;
8511 //Position the handle appropriately
8512 hw->x = x-(hw->x-tx);
8513 hw->y = y-(hw->y-ty);
8514 hw->dir = oppositeDir[hw->dir];
8515 hw->doAutoRotate(true);
8516 hw->flip ^= hflip;
8517 //Move chains
8518 for(int32_t j=0; j<chainlinks.Count(); j++)
8519 {
8520 chainlinks.spr(j)->x += dx;
8521 chainlinks.spr(j)->y += dy;
8522 }
8523 }
8524 hooked_combopos = plpos; //flip positions
8525 }
8526 else reset_hookshot();
8527 }
8528 else if(switching_object) //Switching an object
8529 {
8530 if(switchhook_cost_item > -1)
8531 paymagiccost(switchhook_cost_item);
8532 zfix tx = x, ty = y;
8533 //Position the player at the object
8534 x = switching_object->x;
8535 y = switching_object->y;
8536 dir = oppositeDir[dir];
8537 //Position the object at the player
8538 switching_object->x = tx;
8539 switching_object->y = ty;
8540 if(switching_object->dir == dir || switching_object->dir == oppositeDir[dir])
8541 switching_object->dir = oppositeDir[switching_object->dir];
8542 if(item* it = dynamic_cast<item*>(switching_object))
8543 {
8544 if(itemsbuf[it->id].family == itype_fairy && itemsbuf[it->id].misc3)
8545 {
8546 movefairynew2(it->x, it->y, *it);
8547 }
8548 }
8549 if(w && hw) //!TODO No fucking clue if diagonals work
8550 {
8551 //Calculate chain shift
8552 zfix dx = (x-tx);
8553 zfix dy = (y-ty);
8554 if(w->dir < 4)
8555 {
8556 if(w->dir & 2)
8557 dx = 0;
8558 else dy = 0;
8559 }
8560 //Position the hook head at the handle
8561 w->x = hw->x + dx;
8562 w->y = hw->y + dy;
8563 w->dir = oppositeDir[w->dir];
8564 w->doAutoRotate(true);
8565 byte hflip = (w->dir > 3 ? 3 : ((w->dir & 2) ? 1 : 2));
8566 w->flip ^= hflip;
8567 //Position the handle appropriately
8568 hw->x = x-(hw->x-tx);
8569 hw->y = y-(hw->y-ty);
8570 hw->dir = oppositeDir[hw->dir];
8571 hw->doAutoRotate(true);
8572 hw->flip ^= hflip;
8573 //Move chains
8574 for(int32_t j=0; j<chainlinks.Count(); j++)
8575 {
8576 chainlinks.spr(j)->x += dx;
8577 chainlinks.spr(j)->y += dy;
8578 }
8579 }
8580 }
8581 }
8582 }
8583 else if(!switchhookclk)
8584 {
8585 reset_hookshot();
8586 }
8587 }
8588 else reset_hookshot();
8589 }
8590 else
8591 {
8592 sprite *t;
8593 int32_t i;
8594
8595 for(i=0; i<Lwpns.Count() && (Lwpns.spr(i)->id!=wHSHandle); i++)
8596 {
8597 /* do nothing */
8598 }
8599
8600 t = Lwpns.spr(i);
8601
8602 for(i=0; i<Lwpns.Count(); i++)
8603 {
8604 sprite *s = Lwpns.spr(i);
8605
8606 if(s->id==wHookshot)
8607 {
8608 if (abs((s->y) - y) >= 1)
8609 {
8610 if((s->y)>y)
8611 {
8612 y+=4;
8613
8614 if(Lwpns.idFirst(wHSHandle)!=-1)
8615 {
8616 t->y+=4;
8617 }
8618
8619 hs_starty+=4;
8620 }
8621
8622 if((s->y)<y)
8623 {
8624 y-=4;
8625
8626 if(Lwpns.idFirst(wHSHandle)!=-1)
8627 {
8628 t->y-=4;
8629 }
8630
8631 hs_starty-=4;
8632 }
8633 }
8634 else
8635 {
8636 y = (s->y);
8637 }
8638 if (abs((s->x) - x) >= 1)
8639 {
8640 if((s->x)>x)
8641 {
8642 x+=4;
8643
8644 if(Lwpns.idFirst(wHSHandle)!=-1)
8645 {
8646 t->x+=4;
8647 }
8648
8649 hs_startx+=4;
8650 }
8651
8652 if((s->x)<x)
8653 {
8654 x-=4;
8655
8656 if(Lwpns.idFirst(wHSHandle)!=-1)
8657 {
8658 t->x-=4;
8659 }
8660
8661 hs_startx-=4;
8662 }
8663 }
8664 else
8665 {
8666 x = (s->x);
8667 }
8668 }
8669 }
8670 }
8671 }
8672 }
8673 else
8674 {
8675 Lwpns.del(Lwpns.idFirst(wHSHandle));
8676 reset_hookshot();
8677 }
8678
8679 if(hs_fix)
8680 {
8681 if(dir==up)
8682 {
8683 y=int32_t(y+7)&0xF0;
8684 }
8685
8686 if(dir==down)
8687 {
8688 y=int32_t(y+7)&0xF0;
8689 }
8690
8691 if(dir==left)
8692 {
8693 x=int32_t(x+7)&0xF0;
8694 }
8695
8696 if(dir==right)
8697 {
8698 x=int32_t(x+7)&0xF0;
8699 }
8700
8701 hs_fix=false;
8702 }
8703
8704 }
8705
8706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(!get_bit(quest_rules,qr_NO_L_R_BUTTON_INVENTORY_SWAP))
8707 {
8708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(DrunkrLbtn())
8709 selectNextBWpn(SEL_LEFT);
8710
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 else if(DrunkrRbtn())
8711 selectNextBWpn(SEL_RIGHT);
8712 1888 }
8713
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if (get_bit(quest_rules, qr_SELECTAWPN) && get_bit(quest_rules, qr_USE_EX1_EX2_INVENTORYSWAP))
8714 {
8715 if (rEx3btn())
8716 selectNextAWpn(SEL_LEFT);
8717 else if (rEx4btn())
8718 selectNextAWpn(SEL_RIGHT);
8719 }
8720
8721
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(rPbtn())
8722 {
8723 if( !FFCore.runOnMapScriptEngine() ) //OnMap script replaces the 'onViewMap()' call
8724 onViewMap();
8725 }
8726
2/2
✓ Branch 0 taken 756 times.
✓ Branch 1 taken 1888 times.
2644 for(int32_t i=0; i<Lwpns.Count(); i++)
8727 {
8728 756 weapon *w = ((weapon*)Lwpns.spr(i));
8729
8730
3/6
✓ Branch 0 taken 756 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 756 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 756 times.
756 if(w->id == wArrow || w->id == wBrang || w->id == wCByrna)
8731 addsparkle(i);
8732 756 }
8733
8734
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(Lwpns.idCount(wPhantom))
8735 {
8736 addsparkle2(pDINSFIREROCKET,pDINSFIREROCKETTRAIL);
8737 addsparkle2(pDINSFIREROCKETRETURN,pDINSFIREROCKETTRAILRETURN);
8738 addsparkle2(pNAYRUSLOVEROCKET1,pNAYRUSLOVEROCKETTRAIL1);
8739 addsparkle2(pNAYRUSLOVEROCKET2,pNAYRUSLOVEROCKETTRAIL2);
8740 addsparkle2(pNAYRUSLOVEROCKETRETURN1,pNAYRUSLOVEROCKETTRAILRETURN1);
8741 addsparkle2(pNAYRUSLOVEROCKETRETURN2,pNAYRUSLOVEROCKETTRAILRETURN2);
8742 }
8743
8744 // Pay magic cost for Byrna beams
8745
8746 //Byrna needs a secondary timer, for 254+, as do all items that reduce MP on a per-frae basis. Essentially, we will do % divisor == 0 for that. -Z
8747
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(Lwpns.idCount(wCByrna))
8748 {
8749 weapon *ew = (weapon*)(Lwpns.spr(Lwpns.idFirst(wCByrna)));
8750 int32_t itemid = ew->parentitem;
8751
8752 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
8753 {
8754 for(int32_t i=0; i<Lwpns.Count(); i++)
8755 {
8756 weapon *w = ((weapon*)Lwpns.spr(i));
8757
8758 if(w->id==wCByrna)
8759 {
8760 w->dead=1;
8761 }
8762
8763 }
8764 //kill the sound effect for the orbits -Z 14FEB2019
8765 stop_sfx(itemsbuf[itemid].usesound);
8766 }
8767 else paymagiccost(itemid);
8768 }
8769
8770
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
1888 if(z==0&&fakez==0)
8771 {
8772 1888 switchblock_z = 0;
8773
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(switchblock_offset)
8774 {
8775 switchblock_offset=false;
8776 yofs += 8;
8777 }
8778 1888 }
8779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(!isSideViewHero())
8780 {
8781 1888 int32_t tx = x.getInt()+8,
8782 1888 ty = y.getInt()+8;//(bigHitbox?8:12);
8783
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1888 times.
1888 if(!(unsigned(ty)>175 || unsigned(tx) > 255))
8784 {
8785
2/2
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 5664 times.
7552 for(int32_t q = 0; q < 3; ++q)
8786 {
8787
3/4
✓ Branch 0 taken 3776 times.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3776 times.
5664 if(q && !tmpscr2[q-1].valid) continue;
8788 1888 newcombo const& cmb = combobuf[FFCore.tempScreens[q]->data[COMBOPOS(tx,ty)]];
8789
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if(cmb.type != cCSWITCHBLOCK || !(cmb.usrflags&cflag9)) continue;
8790 int32_t b = 1;
8791 if(tx&8) b <<= 2;
8792 if(ty&8) b <<= 1;
8793 b |= (b<<4); //check equivalent effect flag too
8794 if((cmb.walk&b)==b) //solid and effecting
8795 {
8796 if(z==0&&fakez==0)
8797 {
8798 if(cmb.usrflags&cflag10)
8799 {
8800 if(!switchblock_offset)
8801 {
8802 switchblock_offset=true;
8803 yofs -= 8;
8804 }
8805 }
8806 else
8807 {
8808 if(switchblock_offset)
8809 {
8810 switchblock_offset=false;
8811 yofs += 8;
8812 }
8813 }
8814 }
8815 if(cmb.attributes[2]>0 && switchblock_z>=0)
8816 {
8817 if(z==0&&fakez==0)
8818 switchblock_z = zc_max(switchblock_z,zslongToFix(cmb.attributes[2]));
8819 else if(SWITCHBLOCK_STATE < zslongToFix(cmb.attributes[2]))
8820 {
8821 switchblock_z += zslongToFix(cmb.attributes[2])-SWITCHBLOCK_STATE;
8822 }
8823 }
8824 else switchblock_z = -1;
8825 break;
8826 }
8827 }
8828 1888 }
8829 1888 }
8830 1888 ClearhitHeroUIDs(); //clear them before we advance.
8831 1888 checkhit();
8832
8833 1888 bool forcedeath = dying_flags&DYING_FORCED;
8834 1888 bool norev = (dying_flags&DYING_NOREV);
8835
2/6
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1888 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1888 if(forcedeath || (game->get_life()<=0 && !immortal))
8836 {
8837 if(forcedeath)
8838 game->set_life(0);
8839 if(!norev)
8840 for(size_t slot = 0; slot < 256; ++slot)
8841 {
8842 if(size_t bind = game->get_bottle_slot(slot))
8843 {
8844 bottletype const* bt = &QMisc.bottle_types[bind-1];
8845 if(!(bt->flags&BTFLAG_AUTOONDEATH))
8846 continue;
8847 word toFill[3] = { 0 };
8848 for(size_t q = 0; q < 3; ++q)
8849 {
8850 char c = bt->counter[q];
8851 if(c > -1)
8852 {
8853 if(bt->flags & (1<<q))
8854 {
8855 toFill[q] = (bt->amount[q]==100)
8856 ? game->get_maxcounter(c)
8857 : word((game->get_maxcounter(c)/100.0)*bt->amount[q]);
8858 }
8859 else toFill[q] = bt->amount[q];
8860 if(toFill[q] + game->get_counter(c) > game->get_maxcounter(c))
8861 {
8862 toFill[q] = game->get_maxcounter(c) - game->get_counter(c);
8863 }
8864 }
8865 }
8866 if(bt->flags & BTFLAG_CURESWJINX)
8867 {
8868 swordclk = 0;
8869 verifyAWpn();
8870 }
8871 if(bt->flags & BTFLAG_CUREITJINX)
8872 itemclk = 0;
8873 if(word max = std::max(toFill[0], std::max(toFill[1], toFill[2])))
8874 {
8875 int32_t itemid = find_bottle_for_slot(slot,true);
8876 stop_sfx(QMisc.miscsfx[sfxLOWHEART]); //stop heart beep!
8877 if(itemid > -1)
8878 sfx(itemsbuf[itemid].usesound,pan(x.getInt()));
8879 for(size_t q = 0; q < 20; ++q)
8880 do_death_refill_waitframe();
8881 double inc = max/60.0; //1 second
8882 double xtra[3]{ 0 };
8883 for(size_t q = 0; q < 60; ++q)
8884 {
8885 if(!(q%6) && (toFill[0]||toFill[1]||toFill[2]))
8886 sfx(QMisc.miscsfx[sfxREFILL]);
8887 for(size_t j = 0; j < 3; ++j)
8888 {
8889 xtra[j] += inc;
8890 word f = floor(xtra[j]);
8891 xtra[j] -= f;
8892 if(toFill[j] > f)
8893 {
8894 toFill[j] -= f;
8895 game->change_counter(f,bt->counter[j]);
8896 }
8897 else if(toFill[j])
8898 {
8899 game->change_counter(toFill[j],bt->counter[j]);
8900 toFill[j] = 0;
8901 }
8902 }
8903 do_death_refill_waitframe();
8904 }
8905 for(size_t j = 0; j < 3; ++j)
8906 {
8907 if(toFill[j])
8908 {
8909 game->change_counter(toFill[j],bt->counter[j]);
8910 toFill[j] = 0;
8911 }
8912 }
8913 for(size_t q = 0; q < 20; ++q)
8914 do_death_refill_waitframe();
8915 }
8916 game->set_bottle_slot(slot,bt->next_type);
8917 if(game->get_life() > 0)
8918 {
8919 dying_flags = 0;
8920 forcedeath = false;
8921 break; //Revived! Stop drinking things...
8922 }
8923 }
8924 }
8925
8926 if ( FFCore.getQuestHeaderInfo(vZelda) >= 0x255 )
8927 {
8928 if(forcedeath || (game->get_life()<=0 && !immortal)) //Not saved by fairy
8929 {
8930 // So scripts can have one frame to handle hp zero events
8931 if(norev || false == (last_hurrah = !last_hurrah))
8932 {
8933 dying_flags = 0;
8934 drunkclk=0;
8935 lstunclock = 0;
8936 is_conveyor_stunned = 0;
8937 FFCore.setHeroAction(dying);
8938 FFCore.deallocateAllArrays(SCRIPT_GLOBAL, GLOBAL_SCRIPT_GAME);
8939 FFCore.deallocateAllArrays(SCRIPT_PLAYER, SCRIPT_PLAYER_ACTIVE);
8940 ALLOFF(true,true);
8941 GameFlags |= GAMEFLAG_NO_F6;
8942 if(!debug_enabled)
8943 {
8944 Paused=false;
8945 }
8946 if(!get_bit(quest_rules,qr_ONDEATH_RUNS_AFTER_DEATH_ANIM))
8947 {
8948 FFCore.runOnDeathEngine();
8949 FFCore.deallocateAllArrays(SCRIPT_PLAYER, SCRIPT_PLAYER_DEATH);
8950 }
8951 Playing = false;
8952 heroDeathAnimation();
8953 if(get_bit(quest_rules,qr_ONDEATH_RUNS_AFTER_DEATH_ANIM))
8954 {
8955 Playing = true;
8956 FFCore.runOnDeathEngine();
8957 FFCore.deallocateAllArrays(SCRIPT_PLAYER, SCRIPT_PLAYER_DEATH);
8958 Playing = false;
8959 }
8960 GameFlags &= ~GAMEFLAG_NO_F6;
8961 ALLOFF(true,true);
8962 return true;
8963 }
8964 }
8965 }
8966 else //2.50.x
8967 {
8968 // So scripts can have one frame to handle hp zero events
8969 if(false == (last_hurrah = !last_hurrah))
8970 {
8971 drunkclk=0;
8972 heroDeathAnimation();
8973
8974 return true;
8975 }
8976 }
8977 }
8978 1888 else last_hurrah=false;
8979
8980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(swordclk>0)
8981 {
8982 --swordclk;
8983 if(!swordclk) verifyAWpn();
8984 }
8985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(itemclk>0)
8986 --itemclk;
8987
8988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(inwallm)
8989 {
8990 attackclk=0;
8991 herostep();
8992
8993 if(CarryHero()==false)
8994 restart_level();
8995
8996 solid_update(false);
8997 return false;
8998 }
8999
9000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(ewind_restart)
9001 {
9002 attackclk=0;
9003 restart_level();
9004 xofs=0;
9005 action=none; FFCore.setHeroAction(none);
9006 ewind_restart=false;
9007 solid_update(false);
9008 return false;
9009 }
9010
9011
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(hopclk)
9012 {
9013 action=hopping; FFCore.setHeroAction(hopping);
9014 }
9015
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(fallclk)
9016 {
9017 action=falling; FFCore.setHeroAction(falling);
9018 }
9019
9020 1888 handle_passive_buttons();
9021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(liftclk)
9022 {
9023 if(lift_wpn)
9024 {
9025 action=lifting; FFCore.setHeroAction(lifting);
9026 }
9027 else
9028 {
9029 liftclk = 0;
9030 tliftclk = 0;
9031 }
9032 }
9033
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 else if(lift_wpn)
9034 {
9035 handle_lift(false);
9036 }
9037
9038
9039 // get user input or do other animation
9040 1888 freeze_guys=false; // reset this flag, set it again if holding
9041
9042
9/16
✓ Branch 0 taken 1758 times.
✓ Branch 1 taken 130 times.
✓ Branch 2 taken 1758 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1758 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1758 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1758 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1758 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1758 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1758 times.
1888 if(action != landhold1 && action != landhold2 && action != waterhold1 && action != waterhold2 && action != sidewaterhold1 && action != sidewaterhold2 && fairyclk==0 && holdclk>0)
9043 {
9044 holdclk=0;
9045 }
9046
9047 1888 active_shield_id = refreshActiveShield();
9048 1888 bool sh = active_shield_id > -1;
9049 1888 itemdata const& shield = itemsbuf[active_shield_id];
9050 //Handle direction forcing. This runs every frame so that scripts can interact with dir still.
9051 1888 shield_forcedir = -1;
9052
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1888 if(sh && action != rafting && (shield.flags & ITEM_FLAG11)) //Lock Dir
9053 {
9054 shield_forcedir = dir;
9055 }
9056
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(sh != shield_active) //Toggle active shield on/off
9057 {
9058 shield_active = sh;
9059 if(sh) //Toggle active shield on
9060 {
9061 sfx(shield.usesound2); //'Activate' sfx
9062 }
9063 }
9064
9065 1888 bool isthissolid = false;
9066
3/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 235 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 130 times.
✓ Branch 6 taken 1523 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1888 switch(action)
9067 {
9068 case gothit:
9069 if(attackclk)
9070 if(!doattack())
9071 {
9072 attackclk=spins=0;
9073 tapping=false;
9074 }
9075
9076 break;
9077
9078 case drowning:
9079 case lavadrowning:
9080 case sidedrowning:
9081 {
9082 herostep(); // maybe this line should be elsewhere?
9083
9084 //!DROWN
9085 // Helpful comment to find drowning -Dimi
9086
9087 drop_liftwpn();
9088 if(--drownclk==0)
9089 {
9090 action=none; FFCore.setHeroAction(none);
9091 int32_t water = iswaterex(MAPCOMBO(x.getInt()+7.5,y.getInt()+12), currmap, currscr, -1, x.getInt()+7.5,y.getInt()+12, true, false);
9092 int32_t damage = combobuf[water].attributes[0]/10000L;
9093 //if (damage == 0 && !(combobuf[water].usrflags&cflag7)) damage = (game->get_hp_per_heart()/4);
9094 drownCombo = 0;
9095 if (combobuf[water].type != cWATER) damage = 4;
9096 game->set_life(vbound(game->get_life()-damage,0, game->get_maxlife()));
9097 go_respawn_point();
9098 hclk=48;
9099 }
9100
9101 break;
9102 }
9103 case falling:
9104 {
9105 herostep();
9106 pitfall();
9107 break;
9108 }
9109 case freeze:
9110 case sideswimfreeze:
9111 case scrolling:
9112 235 break;
9113
9114 case casting:
9115 case sideswimcasting:
9116 {
9117 if(magicitem==-1)
9118 {
9119 action=none; FFCore.setHeroAction(none);
9120 }
9121
9122 break;
9123 }
9124 case landhold1:
9125 case landhold2:
9126 {
9127
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 129 times.
130 if(--holdclk <= 0)
9128 {
9129 //restart music
9130
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if(get_bit(quest_rules, qr_HOLDNOSTOPMUSIC) == 0 && (specialcave < GUYCAVE))
9131 playLevelMusic();
9132
9133 1 action=none; FFCore.setHeroAction(none);
9134 1 }
9135 else
9136 129 freeze_guys=true;
9137
9138 130 break;
9139 }
9140 case waterhold1:
9141 case waterhold2:
9142 case sidewaterhold1:
9143 case sidewaterhold2:
9144 {
9145 diveclk=0;
9146
9147 if(--holdclk <= 0)
9148 {
9149 //restart music
9150 if(get_bit(quest_rules, qr_HOLDNOSTOPMUSIC) == 0 && (specialcave < GUYCAVE))
9151 playLevelMusic();
9152
9153 SetSwim();
9154 }
9155 else
9156 freeze_guys=true;
9157
9158 break;
9159 }
9160 case hopping:
9161 {
9162 if(DRIEDLAKE)
9163 {
9164 action=none; FFCore.setHeroAction(none);
9165 hopclk = 0;
9166 diveclk = 0;
9167 break;
9168 }
9169
9170 do_hopping();
9171 break;
9172 }
9173 case inwind:
9174 {
9175 int32_t i=Lwpns.idFirst(wWind);
9176
9177 if(i<0)
9178 {
9179 bool exit=false;
9180
9181 if(whirlwind==255)
9182 {
9183 exit=true;
9184 }
9185 else if(y<=0 && dir==up) y=-1;
9186 else if(y>=160 && dir==down) y=161;
9187 else if(x<=0 && dir==left) x=-1;
9188 else if(x>=240 && dir==right) x=241;
9189 else exit=true;
9190
9191 if(exit)
9192 {
9193 action=none; FFCore.setHeroAction(none);
9194 xofs=0;
9195 whirlwind=0;
9196 lstep=0;
9197 if ( dontdraw < 2 ) dontdraw=0;
9198 set_respawn_point();
9199 }
9200 }
9201 /*
9202 else if (((weapon*)Lwpns.spr(i))->dead==1)
9203 {
9204 whirlwind=255;
9205 }
9206 */
9207 else
9208 {
9209 x=Lwpns.spr(i)->x;
9210 y=Lwpns.spr(i)->y;
9211 dir=Lwpns.spr(i)->dir;
9212 }
9213 }
9214 break;
9215 case lifting:
9216 handle_lift();
9217 break;
9218
9219 case sideswimming:
9220 case sideswimattacking:
9221 case sideswimhit:
9222 case swimhit:
9223 case swimming:
9224 {
9225 if(DRIEDLAKE)
9226 {
9227 action=none; FFCore.setHeroAction(none);
9228 hopclk=0;
9229 break;
9230 }
9231
9232 bool shouldbreak = (action == sideswimhit || action == swimhit); //!DIMITODO: "Can walk while hurt" compat needs to be added here.
9233
9234 if((frame&1) && !shouldbreak)
9235 herostep();
9236
9237 if (_walkflag(x+7,y+(bigHitbox?6:11),1,SWITCHBLOCK_STATE)
9238 || _walkflag(x+7,y+(bigHitbox?9:12),1,SWITCHBLOCK_STATE)
9239 || _walkflag(x+8,y+(bigHitbox?6:11),1,SWITCHBLOCK_STATE)
9240 || _walkflag(x+8,y+(bigHitbox?9:12),1,SWITCHBLOCK_STATE)) isthissolid = true;
9241 if ((get_bit(quest_rules, qr_NO_HOPPING) || CanSideSwim()) && !isthissolid) //Since hopping won't be set with this on, something needs to kick Hero out of water...
9242 {
9243 if(!iswaterex(MAPCOMBO(x.getInt()+4,y.getInt()+9), currmap, currscr, -1, x.getInt()+4,y.getInt()+9, true, false)||!iswaterex(MAPCOMBO(x.getInt()+4,y.getInt()+15), currmap, currscr, -1, x.getInt()+4,y.getInt()+15, true, false)
9244 || !iswaterex(MAPCOMBO(x.getInt()+11,y.getInt()+9), currmap, currscr, -1, x.getInt()+11,y.getInt()+9, true, false)||!iswaterex(MAPCOMBO(x.getInt()+11,y.getInt()+15), currmap, currscr, -1, x.getInt()+11,y.getInt()+15, true, false))
9245 {
9246 hopclk=0;
9247 diveclk=0;
9248 if (action != sideswimattacking && action != attacking) {action=none; FFCore.setHeroAction(none);}
9249 else {action=attacking; FFCore.setHeroAction(attacking);}
9250 hopdir=-1;
9251 }
9252 }
9253 if (shouldbreak) break;
9254 if (action == swimming || action == sideswimming || action == sideswimattacking)
9255 {
9256 int32_t watercheck = iswaterex(MAPCOMBO(x.getInt()+7.5,y.getInt()+12), currmap, currscr, -1, x.getInt()+7.5,y.getInt()+12, true, false);
9257 if (combobuf[watercheck].usrflags&cflag2)
9258 {
9259 if (current_item(combobuf[watercheck].attribytes[2]) < combobuf[watercheck].attribytes[3])
9260 {
9261 onpassivedmg = true;
9262 if (damageovertimeclk == 0)
9263 {
9264 int32_t curhp = game->get_life();
9265 if (combobuf[watercheck].usrflags&cflag5) game->set_life(vbound(game->get_life()+ringpower(combobuf[watercheck].attributes[1]/10000L), 0, game->get_maxlife())); //Affected by rings
9266 else game->set_life(vbound(game->get_life()+(combobuf[watercheck].attributes[1]/10000L), 0, game->get_maxlife()));
9267 if ((combobuf[watercheck].attributes[2]/10000L) && (game->get_life() != curhp || !(combobuf[watercheck].usrflags&cflag6))) sfx(combobuf[watercheck].attributes[2]/10000L);
9268 if (game->get_life() < curhp && combobuf[watercheck].usrflags&cflag7)
9269 {
9270 hclk = 48;
9271 hitdir = -1;
9272 if (IsSideSwim()) {action = sideswimhit; FFCore.setHeroAction(sideswimhit);}
9273 else {action = swimhit; FFCore.setHeroAction(swimhit);}
9274 }
9275 }
9276 if (combobuf[watercheck].attribytes[1] > 0)
9277 {
9278 if (!damageovertimeclk || damageovertimeclk > combobuf[watercheck].attribytes[1]) damageovertimeclk = combobuf[watercheck].attribytes[1];
9279 else --damageovertimeclk;
9280 }
9281 else damageovertimeclk = 0;
9282 }
9283 else damageovertimeclk = 0;
9284 }
9285 else damageovertimeclk = 0;
9286 //combobuf[watercheck].attributes[0]
9287 }
9288
9289 }
9290 [[fallthrough]];
9291 default:
9292 1523 movehero(); // call the main movement routine
9293 1523 }
9294
9295
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if(shield_forcedir > -1 && action != rafting)
9296 dir = shield_forcedir;
9297
9298
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(!get_bit(quest_rules,qr_OLD_RESPAWN_POINTS))
9299 set_respawn_point(false); //Keep the 'last safe location' updated!
9300
9301 // check for ladder removal
9302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(diagonalMovement)
9303 {
9304 if(ladderx+laddery)
9305 {
9306 if(ladderdir==up)
9307 {
9308 if((laddery-y.getInt()>=(16+(ladderstart==dir?ladderstart==down?1:0:0))) || (laddery-y.getInt()<=(-16-(ladderstart==dir?ladderstart==up?1:0:0))) || (abs(ladderx-x.getInt())>8))
9309 {
9310 reset_ladder();
9311 }
9312 }
9313 else
9314 {
9315 if((abs(laddery-y.getInt())>8) || (ladderx-x.getInt()>=(16+(ladderstart==dir?ladderstart==right?1:0:0))) || (ladderx-x.getInt()<=(-16-(ladderstart==dir?ladderstart==left?1:0:0))))
9316 {
9317 reset_ladder();
9318 }
9319 }
9320 }
9321 }
9322 else
9323 {
9324
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1875 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
1888 if((abs(laddery-y.getInt())>=16) || (abs(ladderx-x.getInt())>=16))
9325 {
9326 1888 reset_ladder();
9327 1888 }
9328 }
9329
9330
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1884 times.
1888 if(ilswim)
9331 4 landswim++;
9332 1884 else landswim=0;
9333
9334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(hopclk!=0xFF) ilswim=false;
9335
9336
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1883 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
1888 if((!loaded_guys) && (frame - newscr_clk >= 1))
9337 {
9338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(tmpscr->room==rGANON)
9339 {
9340 ganon_intro();
9341 }
9342 else
9343 {
9344 5 loadguys();
9345 }
9346 5 }
9347
9348
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1875 times.
1888 if(frame - newscr_clk >= 2)
9349 {
9350 1875 loadenemies();
9351 1875 }
9352
9353 // check lots of other things
9354 1888 checkscroll();
9355
9356
4/8
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1888 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1888 times.
1888 if(action!=inwind && action!=drowning && action != sidedrowning && action!=lavadrowning)
9357 {
9358 1888 checkspecial();
9359 1888 checkitems();
9360 1888 checklocked(); //This has issues if Hero's action is WALKING, in 8-way moveent.
9361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(get_bit(quest_rules, qr_OLD_LOCKBLOCK_COLLISION))
9362 {
9363 1888 oldchecklockblock();
9364 1888 oldcheckbosslockblock();
9365 1888 }
9366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(get_bit(quest_rules,qr_OLD_CHEST_COLLISION))
9367 {
9368 1888 oldcheckchest(cCHEST);
9369 1888 oldcheckchest(cLOCKEDCHEST);
9370 1888 oldcheckchest(cBOSSCHEST);
9371 1888 }
9372 1888 checkpushblock();
9373 1888 checkswordtap();
9374
9375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(hookshot_frozen==false)
9376 {
9377 1888 checkspecial2(&lsave);
9378 1888 }
9379
9380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(action==won)
9381 {
9382 return true;
9383 }
9384 1888 }
9385
9386 // Somehow Hero was displaced from the fairy flag...
9387
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1888 if(fairyclk && action != freeze && action != sideswimfreeze)
9388 {
9389 fairyclk = holdclk = refill_why = 0;
9390 }
9391
9392
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
1888 if((!activated_timed_warp) && (tmpscr->timedwarptics>0))
9393 {
9394 tmpscr->timedwarptics--;
9395
9396 if(tmpscr->timedwarptics==0)
9397 {
9398 activated_timed_warp=true;
9399
9400 if(tmpscr->flags4 & fTIMEDDIRECT)
9401 {
9402 didpit=true;
9403 pitx=x;
9404 pity=y;
9405 }
9406
9407 int32_t index2 = 0;
9408
9409 if(tmpscr->flags5 & fRANDOMTIMEDWARP) index2=zc_oldrand()%4;
9410
9411 sdir = dir;
9412 dowarp(1,index2);
9413 }
9414 }
9415
9416 1888 bool awarp = false;
9417 //!DIMI: Global Combo Effects (AUTO STUFF)
9418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 for(auto& p : slopes)
9419 {
9420 slope_object& s = p.second;
9421 s.updateslope(); //sets old x/y poses
9422 }
9423
2/2
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 332288 times.
334176 for(int32_t i=0; i<176; ++i)
9424 {
9425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1329152 times.
1329152 for(int32_t layer=0; layer<7; ++layer)
9426 {
9427
2/2
✓ Branch 0 taken 996864 times.
✓ Branch 1 taken 332288 times.
1329152 int32_t cid = ( layer ) ? MAPCOMBOL(layer,COMBOX(i),COMBOY(i)) : MAPCOMBO(COMBOX(i),COMBOY(i));
9428 1329152 newcombo const& cmb = combobuf[cid];
9429
9430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1329152 times.
1329152 if(!get_bit(quest_rules,qr_AUTOCOMBO_ANY_LAYER))
9431 {
9432
2/2
✓ Branch 0 taken 332288 times.
✓ Branch 1 taken 996864 times.
1329152 if(layer > 2) break;
9433
3/4
✓ Branch 0 taken 332288 times.
✓ Branch 1 taken 664576 times.
✓ Branch 2 taken 332288 times.
✗ Branch 3 not taken.
996864 if (layer == 1 && !get_bit(quest_rules,qr_AUTOCOMBO_LAYER_1)) continue;
9434
3/4
✓ Branch 0 taken 332288 times.
✓ Branch 1 taken 332288 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 332288 times.
664576 if (layer == 2 && !get_bit(quest_rules,qr_AUTOCOMBO_LAYER_2)) continue;
9435 332288 }
9436 332288 int32_t ind=0;
9437
9438 //AUTOMATIC TRIGGER CODE
9439
1/2
✓ Branch 0 taken 332288 times.
✗ Branch 1 not taken.
332288 if (cmb.triggerflags[1]&combotriggerAUTOMATIC)
9440 {
9441 do_trigger_combo(layer, i);
9442 }
9443
9444 //AUTO WARP CODE
9445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 332288 times.
332288 if(!(cmb.triggerflags[0] & combotriggerONLYGENTRIG))
9446 {
9447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 332288 times.
332288 if(cmb.type==cAWARPA)
9448 {
9449 awarp=true;
9450 ind=0;
9451 }
9452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 332288 times.
332288 else if(cmb.type==cAWARPB)
9453 {
9454 awarp=true;
9455 ind=1;
9456 }
9457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 332288 times.
332288 else if(cmb.type==cAWARPC)
9458 {
9459 awarp=true;
9460 ind=2;
9461 }
9462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 332288 times.
332288 else if(cmb.type==cAWARPD)
9463 {
9464 awarp=true;
9465 ind=3;
9466 }
9467
1/2
✓ Branch 0 taken 332288 times.
✗ Branch 1 not taken.
332288 else if(cmb.type==cAWARPR)
9468 {
9469 awarp=true;
9470 ind=zc_oldrand()%4;
9471 }
9472 332288 }
9473
1/2
✓ Branch 0 taken 332288 times.
✗ Branch 1 not taken.
332288 if(awarp)
9474 {
9475 if(tmpscr->flags5&fDIRECTAWARP)
9476 {
9477 didpit=true;
9478 pitx=x;
9479 pity=y;
9480 }
9481
9482 sdir = dir;
9483 dowarp(1,ind);
9484 break;
9485 }
9486 332288 }
9487
1/2
✓ Branch 0 taken 332288 times.
✗ Branch 1 not taken.
332288 if(awarp) break;
9488 332288 }
9489
9490 1888 awarp=false;
9491
9492 1888 word c = tmpscr->numFFC();
9493
2/2
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 1888 times.
3776 for(word i=0; i<c; i++)
9494 {
9495 1888 int32_t ind=0;
9496
9497 1888 newcombo const& cmb = combobuf[tmpscr->ffcs[i].getData()];
9498
9499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(!(cmb.triggerflags[0] & combotriggerONLYGENTRIG))
9500 {
9501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(cmb.type==cAWARPA)
9502 {
9503 awarp=true;
9504 ind=0;
9505 }
9506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 else if(cmb.type==cAWARPB)
9507 {
9508 awarp=true;
9509 ind=1;
9510 }
9511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 else if(cmb.type==cAWARPC)
9512 {
9513 awarp=true;
9514 ind=2;
9515 }
9516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 else if(cmb.type==cAWARPD)
9517 {
9518 awarp=true;
9519 ind=3;
9520 }
9521
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 else if(cmb.type==cAWARPR)
9522 {
9523 awarp=true;
9524 ind=zc_oldrand()%4;
9525 }
9526 1888 }
9527
9528
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(awarp)
9529 {
9530 if(tmpscr->flags5&fDIRECTAWARP)
9531 {
9532 didpit=true;
9533 pitx=x;
9534 pity=y;
9535 }
9536
9537 sdir = dir;
9538 dowarp(1,ind);
9539 break;
9540 }
9541 1888 }
9542 1888 zfix dx, dy;
9543
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1888 if (sideview_mode() && !on_sideview_solid_oldpos(x, y,old_x,old_y, false, 1) && on_sideview_solid_oldpos(x, y,old_x,old_y, false, 2) && !toogam)
9544 {
9545 if (slide_slope(this, dx, dy, slopeid))
9546 {
9547 onplatid = 5;
9548 if (dx || dy) push_move(dx, dy);
9549 }
9550 }
9551
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if (onplatid <= 0) slopeid = 0;
9552 else --onplatid;
9553
2/2
✓ Branch 0 taken 1603 times.
✓ Branch 1 taken 285 times.
1888 bool onplatform = (on_sideview_solid_oldpos(x, y,old_x,old_y, false, 1) && !Up());
9554
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1888 times.
1888 for (auto q = 0; (check_slope(this, true) && !toogam) && q < 2; ++q)
9555 {
9556 if (check_slope(this, true) && !toogam)
9557 {
9558 slope_info const& s = get_slope(this, true).get_info();
9559 bool staircheck = false;
9560 if (s.slope() != slopeid && slopeid) staircheck = true;
9561 if (onplatform) staircheck = true;
9562 slope_push_int(s, this, dx, dy, staircheck, platformfell2);
9563
9564 if (dx || dy)
9565 {
9566 int32_t pushret = push_move(dx,dy);
9567 onplatform = (on_sideview_solid_oldpos(x, y,old_x,old_y, false, 1) && !Up());
9568 if (s.slope() != slopeid && slopeid) staircheck = true;
9569 if (onplatform) staircheck = true;
9570 if(sideview_mode() && slopeid)
9571 onplatid = 5;
9572 if (pushret == 1)
9573 {
9574 dx = -1;
9575 dy = 0;
9576 slope_push_int(s, this, dx, dy, staircheck);
9577 push_move(dx,dy);
9578 }
9579 if (pushret == 2)
9580 {
9581 dx = 0;
9582 dy = -1;
9583 slope_push_int(s, this, dx, dy, staircheck);
9584 push_move(dx,dy);
9585 }
9586 }
9587 }
9588 }
9589
9590
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(ffwarp)
9591 {
9592 if(ffpit)
9593 {
9594 ffpit=false;
9595 didpit=true;
9596 pitx=x;
9597 pity=y;
9598 }
9599
9600 ffwarp=false;
9601 dowarp(1,0);
9602 }
9603
9604 //Hero->WarpEx
9605
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if ( FFCore.warpex[wexActive] )
9606 {
9607 if(DEVLOGGING) zprint("Running warpex from hero.cpp\n");
9608 FFCore.warpex[wexActive] = 0;
9609 int32_t temp_warpex[wexActive] = {0}; //to hold the values as we clear the FFCore array. -Z
9610 for ( int32_t q = 0; q < wexActive; q++ )
9611 {
9612 temp_warpex[q] = FFCore.warpex[q];
9613 FFCore.warpex[q] = 0;
9614 }
9615 FFCore.warp_player( temp_warpex[wexType], temp_warpex[wexDMap], temp_warpex[wexScreen], temp_warpex[wexX],
9616 temp_warpex[wexY], temp_warpex[wexEffect], temp_warpex[wexSound], temp_warpex[wexFlags], temp_warpex[wexDir]);
9617 }
9618
9619 // walk through bombed doors and fake walls
9620 1888 bool walk=false;
9621 1888 int32_t dtype=dBOMBED;
9622
9623
2/2
✓ Branch 0 taken 1885 times.
✓ Branch 1 taken 3 times.
1888 if(pushing>=24) dtype=dWALK;
9624
9625
1/18
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
1888 if(isdungeon() && action!=freeze && action != sideswimfreeze && loaded_guys && !inlikelike && !diveclk && action!=rafting && !lstunclock && !is_conveyor_stunned)
9626 {
9627 if(((dtype==dBOMBED)?DrunkUp():dir==up) && ((diagonalMovement||NO_GRIDLOCK)?x>112&&x<128:x==120) && y<=32 && tmpscr->door[0]==dtype)
9628 {
9629 walk=true;
9630 dir=up;
9631 }
9632
9633 if(((dtype==dBOMBED)?DrunkDown():dir==down) && ((diagonalMovement||NO_GRIDLOCK)?x>112&&x<128:x==120) && y>=128 && tmpscr->door[1]==dtype)
9634 {
9635 walk=true;
9636 dir=down;
9637 }
9638
9639 if(((dtype==dBOMBED)?DrunkLeft():dir==left) && x<=32 && ((diagonalMovement||NO_GRIDLOCK)?y>72&&y<88:y==80) && tmpscr->door[2]==dtype)
9640 {
9641 walk=true;
9642 dir=left;
9643 }
9644
9645 if(((dtype==dBOMBED)?DrunkRight():dir==right) && x>=208 && ((diagonalMovement||NO_GRIDLOCK)?y>72&&y<88:y==80) && tmpscr->door[3]==dtype)
9646 {
9647 walk=true;
9648 dir=right;
9649 }
9650 }
9651
9652
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(walk)
9653 {
9654 hclk=0;
9655 drawguys=false;
9656
9657 if(dtype==dWALK)
9658 {
9659 sfx(tmpscr->secretsfx);
9660 }
9661
9662 action=none; FFCore.setHeroAction(none);
9663 stepforward(29, true);
9664 action=scrolling; FFCore.setHeroAction(scrolling);
9665 pushing=false;
9666 }
9667
9668
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1888 if( game->get_life() <= (game->get_hp_per_heart()) && !(game->get_maxlife() <= (game->get_hp_per_heart())) && (heart_beep_timer > -3))
9669 {
9670 if(heart_beep)
9671 {
9672 cont_sfx(QMisc.miscsfx[sfxLOWHEART]);
9673 }
9674 else
9675 {
9676 if ( heart_beep_timer == -1 )
9677 {
9678 heart_beep_timer = 70;
9679 }
9680
9681 if ( heart_beep_timer > 0 )
9682 {
9683 --heart_beep_timer;
9684 cont_sfx(QMisc.miscsfx[sfxLOWHEART]);
9685 }
9686 else
9687 {
9688 stop_sfx(QMisc.miscsfx[sfxLOWHEART]);
9689 }
9690 }
9691 }
9692 else
9693 {
9694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if ( heart_beep_timer > -2 )
9695 {
9696 1888 heart_beep_timer = -1;
9697 1888 stop_sfx(QMisc.miscsfx[sfxLOWHEART]);
9698 1888 }
9699 }
9700
9701
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(rSbtn())
9702 {
9703 int32_t tmp_subscr_clk = frame;
9704
9705 int32_t save_type = 0;
9706 switch(lsave)
9707 {
9708 case 0:
9709 {
9710 if( FFCore.runActiveSubscreenScriptEngine() )
9711 {
9712 break;
9713 }
9714 else if ( !stopSubscreenFalling() )
9715 {
9716 conveyclk=3;
9717 dosubscr(&QMisc);
9718 newscr_clk += frame - tmp_subscr_clk;
9719 }
9720 break;
9721 }
9722
9723
9724 case 2:
9725 save_type = 1;
9726 [[fallthrough]];
9727 case 1:
9728 if(last_savepoint_id)
9729 trigger_save(combobuf[last_savepoint_id]);
9730 else save_game((tmpscr->flags4&fSAVEROOM) != 0, save_type); //sanity?
9731 break;
9732 }
9733 }
9734
9735
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 1752 times.
1888 if (!checkstab() )
9736 {
9737 /*
9738 for(int32_t q=0; q<176; q++)
9739 {
9740 set_bit(screengrid,q,0);
9741 }
9742
9743 for(int32_t q=0; q<MAXFFCS; q++)
9744 set_bit(ffcgrid, q, 0);
9745 */
9746 1752 }
9747
9748 1888 check_conveyor();
9749 1888 PhantomsCleanup();
9750 //Try to time the hammer pound so that Hero can;t change direction while it occurs.
9751
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(attack==wHammer)
9752 {
9753 if(attackclk==12 && z==0 && fakez==0 && sideviewhammerpound())
9754 {
9755 switch(dir) //Hero's dir
9756 {
9757 case up:
9758 decorations.add(new dHammerSmack(x-1, y-4, dHAMMERSMACK, 0));
9759 break;
9760
9761 case down:
9762 decorations.add(new dHammerSmack(x+8, y+28, dHAMMERSMACK, 0));
9763 break;
9764
9765 case left:
9766 decorations.add(new dHammerSmack(x-13, y+14, dHAMMERSMACK, 0));
9767 break;
9768
9769 case right:
9770 decorations.add(new dHammerSmack(x+21, y+14, dHAMMERSMACK, 0));
9771 break;
9772 }
9773
9774 }
9775 }
9776
9777 1888 handleSpotlights();
9778
9779
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(getOnSideviewLadder())
9780 {
9781 if(!canSideviewLadder() || jumping<0 || fall!=0 || fakefall!=0)
9782 {
9783 setOnSideviewLadder(false);
9784 }
9785 else if(CANFORCEFACEUP)
9786 {
9787 setDir(up);
9788 }
9789 }
9790
9791 1888 return false;
9792 1888 }
9793
9794 bool HeroClass::push_pixel(zfix dx, zfix dy)
9795 {
9796 ASSERT(abs(dx) <= 1 && abs(dy) <= 1);
9797 if(dx && dy)
9798 {
9799 bool r = push_pixel(0,dy);
9800 bool r2 = push_pixel(dx,0);
9801 return r && r2;
9802 }
9803 if(dx < 0)
9804 {
9805 if(!(solpush_walkflag(x+dx,y+(bigHitbox?0:8),1,this)
9806 || solpush_walkflag(x+dx,y+8,1,this)
9807 || (y.getInt()&7?solpush_walkflag(x+dx,y+16,1,this):0)))
9808 {
9809 x += dx;
9810 return true;
9811 }
9812 return false;
9813 }
9814 else if(dx > 0)
9815 {
9816 if(!(solpush_walkflag(x+15+dx,y+(bigHitbox?0:8),1,this)
9817 || solpush_walkflag(x+15+dx,y+8,1,this)
9818 || (y.getInt()&7?solpush_walkflag(x+15+dx,y+16,1,this):0)))
9819 {
9820 x += dx;
9821 return true;
9822 }
9823 return false;
9824 }
9825 else if(dy < 0)
9826 {
9827 if(!(solpush_walkflag(x,y+(bigHitbox?0:8)+dy,2,this)
9828 || (x.getInt()&7?solpush_walkflag(x+16,y+(bigHitbox?0:8)+dy,1,this):0)))
9829 {
9830 y += dy;
9831 return true;
9832 }
9833 return false;
9834 }
9835 else if(dy > 0)
9836 {
9837 if(!(solpush_walkflag(x,y+15+dy,2,this)
9838 || (x.getInt()&7?solpush_walkflag(x+16,y+15+dy,1,this):0)))
9839 {
9840 y += dy;
9841 return true;
9842 }
9843 return false;
9844 }
9845 return false;
9846 }
9847 int32_t HeroClass::push_move(zfix dx, zfix dy)
9848 {
9849 int32_t ret = 0;
9850 while(dx || dy)
9851 {
9852 if(check_pitslide() != -1)
9853 break;
9854 if(dy)
9855 {
9856 zfix cy = (abs(dy) >= 1) ? sign(dy) : dy;
9857 dy -= cy;
9858 if(!push_pixel(0,cy))
9859 {
9860 dy = 0;
9861 ret |= 2;
9862 }
9863 }
9864 if(dx)
9865 {
9866 zfix cx = (abs(dx) >= 1) ? sign(dx) : dx;
9867 dx -= cx;
9868 if(!push_pixel(cx,0))
9869 {
9870 dx = 0;
9871 ret |= 1;
9872 }
9873 }
9874 }
9875 return ret;
9876 }
9877
9878 1888 bool HeroClass::setSolid(bool set)
9879 {
9880
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 bool actual = set && !toogam; //not solid when noclipping
9881 1888 bool ret = solid_object::setSolid(actual);
9882 1888 solid = set;
9883 1888 return ret;
9884 }
9885
9886 void HeroClass::solid_push(solid_object* obj)
9887 {
9888 if(obj == this) return; //can't push self
9889
9890 zfix dx, dy;
9891 int32_t hdir = -1;
9892 solid_push_int(obj,dx,dy,hdir);
9893
9894 if(!dx && !dy) return;
9895
9896 obj->doContactDamage(hdir);
9897
9898 bool t = obj->getTempNonsolid();
9899 obj->setTempNonsolid(true);
9900
9901 push_move(dx,dy);
9902
9903 obj->setTempNonsolid(t);
9904 }
9905
9906 // A routine used exclusively by startwpn,
9907 // to switch Hero's weapon if his current weapon (bombs) was depleted.
9908 void HeroClass::deselectbombs(int32_t super)
9909 {
9910 if ( get_bit(quest_rules,qr_NEVERDISABLEAMMOONSUBSCREEN) || itemsbuf[game->forced_awpn].family == itype_bomb || itemsbuf[game->forced_bwpn].family == itype_bomb || itemsbuf[game->forced_xwpn].family == itype_bomb || itemsbuf[game->forced_ywpn].family == itype_bomb) return;
9911 if(getItemFamily(itemsbuf,Bwpn&0x0FFF)==(super? itype_sbomb : itype_bomb) && (directWpn<0 || Bwpn==directWpn))
9912 {
9913 int32_t temp = selectWpn_new(SEL_VERIFY_LEFT, game->bwpn, game->awpn, get_bit(quest_rules,qr_SET_XBUTTON_ITEMS) ? game->xwpn : -1, get_bit(quest_rules,qr_SET_YBUTTON_ITEMS) ? game->ywpn : -1);
9914 Bwpn = Bweapon(temp);
9915 directItemB = directItem;
9916 game->bwpn = temp;
9917 }
9918
9919 else if (getItemFamily(itemsbuf,Xwpn&0x0FFF)==(super? itype_sbomb : itype_bomb) && (directWpn<0 || Xwpn==directWpn))
9920 {
9921 int32_t temp = selectWpn_new(SEL_VERIFY_LEFT, game->xwpn, game->bwpn, game->awpn, get_bit(quest_rules,qr_SET_YBUTTON_ITEMS) ? game->ywpn : -1);
9922 Xwpn = Bweapon(temp);
9923 directItemX = directItem;
9924 game->xwpn = temp;
9925 }
9926 else if (getItemFamily(itemsbuf,Ywpn&0x0FFF)==(super? itype_sbomb : itype_bomb) && (directWpn<0 || Ywpn==directWpn))
9927 {
9928 int32_t temp = selectWpn_new(SEL_VERIFY_LEFT, game->ywpn, game->bwpn, get_bit(quest_rules,qr_SET_XBUTTON_ITEMS) ? game->xwpn : -1, game->awpn);
9929 Ywpn = Bweapon(temp);
9930 directItemY = directItem;
9931 game->ywpn = temp;
9932 }
9933 else
9934 {
9935 int32_t temp = selectWpn_new(SEL_VERIFY_LEFT, game->awpn, game->bwpn, get_bit(quest_rules,qr_SET_XBUTTON_ITEMS) ? game->xwpn : -1, get_bit(quest_rules,qr_SET_YBUTTON_ITEMS) ? game->ywpn : -1);
9936 Awpn = Bweapon(temp);
9937 directItemA = directItem;
9938 game->awpn = temp;
9939 }
9940 }
9941
9942 int32_t potion_life=0;
9943 int32_t potion_magic=0;
9944
9945 bool HeroClass::mirrorBonk()
9946 {
9947 zfix tx = x, ty = y, tz = z;
9948 WalkflagInfo info = walkflag(x,y+(bigHitbox?0:8),2,up);
9949 info = info || walkflagMBlock(x+8,y+(bigHitbox?0:8));
9950 execute(info);
9951 bool fail = info.isUnwalkable();
9952
9953 if(!fail) //not solid, but check for water/pits...
9954 {
9955 //{ Check water collision.... GAAAAAAAH THIS IS A MESS
9956 int32_t water = 0;
9957 int32_t types[4] = {0};
9958 int32_t x1 = x+4, x2 = x+11,
9959 y1 = y+9, y2 = y+15;
9960 if (get_bit(quest_rules, qr_SMARTER_WATER))
9961 {
9962 if (iswaterex(0, currmap, currscr, -1, x1, y1, true, false) &&
9963 iswaterex(0, currmap, currscr, -1, x1, y2, true, false) &&
9964 iswaterex(0, currmap, currscr, -1, x2, y1, true, false) &&
9965 iswaterex(0, currmap, currscr, -1, x2, y2, true, false)) water = iswaterex(0, currmap, currscr, -1, (x2+x1)/2,(y2+y1)/2, true, false);
9966 }
9967 else
9968 {
9969 types[0] = COMBOTYPE(x1,y1);
9970
9971 if(MAPFFCOMBO(x1,y1))
9972 types[0] = FFCOMBOTYPE(x1,y1);
9973
9974 types[1] = COMBOTYPE(x1,y2);
9975
9976 if(MAPFFCOMBO(x1,y2))
9977 types[1] = FFCOMBOTYPE(x1,y2);
9978
9979 types[2] = COMBOTYPE(x2,y1);
9980
9981 if(MAPFFCOMBO(x2,y1))
9982 types[2] = FFCOMBOTYPE(x2,y1);
9983
9984 types[3] = COMBOTYPE(x2,y2);
9985
9986 if(MAPFFCOMBO(x2,y2))
9987 types[3] = FFCOMBOTYPE(x2,y2);
9988
9989 int32_t typec = COMBOTYPE((x2+x1)/2,(y2+y1)/2);
9990 if(MAPFFCOMBO((x2+x1)/2,(y2+y1)/2))
9991 typec = FFCOMBOTYPE((x2+x1)/2,(y2+y1)/2);
9992
9993 if(combo_class_buf[types[0]].water && combo_class_buf[types[1]].water &&
9994 combo_class_buf[types[2]].water && combo_class_buf[types[3]].water && combo_class_buf[typec].water)
9995 water = typec;
9996 }
9997 if(water > 0)
9998 {
9999 if(current_item(itype_flippers) <= 0 || current_item(itype_flippers) < combobuf[water].attribytes[0] || ((combobuf[water].usrflags&cflag1) && !(itemsbuf[current_item_id(itype_flippers)].flags & ITEM_FLAG3)))
10000 {
10001 fail = true;
10002 }
10003 }
10004 //}
10005 if(pitslide() || fallclk)
10006 fail = true;
10007 fallclk = 0;
10008 }
10009 x = tx; y = ty; z = tz;
10010 return fail;
10011 }
10012
10013 void HeroClass::doMirror(int32_t mirrorid)
10014 {
10015 if(z > 0 || fakez > 0) return; //No mirror in air
10016 if(mirrorid < 0)
10017 mirrorid = current_item_id(itype_mirror);
10018 if(mirrorid < 0) return;
10019
10020 if((tmpscr->flags9&fDISABLE_MIRROR) || !(checkbunny(mirrorid) && checkmagiccost(mirrorid)))
10021 {
10022 if(QMisc.miscsfx[sfxERROR])
10023 sfx(QMisc.miscsfx[sfxERROR]);
10024 return;
10025 }
10026 static const int32_t sens = 4; //sensitivity of 'No Mirror' combos (0 most, 8 least)
10027 int32_t posarr[] = {COMBOPOS(x+sens,y+sens), COMBOPOS(x+sens,y+15-sens),
10028 COMBOPOS(x+15-sens,y+sens), COMBOPOS(x+15-sens,y+15-sens)};
10029 for(auto pos : posarr)
10030 {
10031 if(HASFLAG_ANY(mfNOMIRROR, pos)) //"No Mirror" flag touching the player
10032 {
10033 if(QMisc.miscsfx[sfxERROR])
10034 sfx(QMisc.miscsfx[sfxERROR]);
10035 return;
10036 }
10037 }
10038
10039 itemdata const& mirror = itemsbuf[mirrorid];
10040 if(DMaps[currdmap].flags & dmfMIRRORCONTINUE)
10041 {
10042 paymagiccost(mirrorid);
10043 if(mirror.usesound2) sfx(mirror.usesound2);
10044
10045 doWarpEffect(mirror.misc2, true);
10046 if(mirror.flags & ITEM_FLAG2) //Act as F6->Continue
10047 {
10048 Quit = qCONT;
10049 skipcont = 1;
10050 }
10051 else //Act as Farore's Wind
10052 {
10053 int32_t nayrutemp=nayruitem;
10054 restart_level();
10055 nayruitem=nayrutemp;
10056 magicitem=-1;
10057 magiccastclk=0;
10058 if ( Hero.getDontDraw() < 2 ) { Hero.setDontDraw(0); }
10059 }
10060 }
10061 else
10062 {
10063 int32_t destdmap = DMaps[currdmap].mirrorDMap;
10064 int32_t offscr = currscr - DMaps[currdmap].xoff;
10065 if(destdmap < 0)
10066 return;
10067 int32_t destscr = DMaps[destdmap].xoff + offscr;
10068 if((offscr%16 != destscr%16) || unsigned(destscr) >= 0x80)
10069 return;
10070 paymagiccost(mirrorid);
10071
10072 //Store some values to restore if 'warp fails'
10073 int32_t tLastEntrance = lastentrance,
10074 tLastEntranceDMap = lastentrance_dmap,
10075 tContScr = game->get_continue_scrn(),
10076 tContDMap = game->get_continue_dmap(),
10077 tPortalDMap = game->portalsrcdmap;
10078 int32_t sourcescr = currscr, sourcedmap = currdmap;
10079 zfix tx = x, ty = y, tz = z;
10080 game->portalsrcdmap = -1;
10081 action = none; FFCore.setHeroAction(none);
10082
10083 //Warp to new dmap
10084 FFCore.warp_player(wtIWARP, destdmap, destscr, -1, -1, mirror.misc1,
10085 mirror.usesound, 0, -1);
10086
10087 //Check for valid landing location
10088 if(mirrorBonk()) //Invalid landing, warp back!
10089 {
10090 action = none; FFCore.setHeroAction(none);
10091 lastentrance = tLastEntrance;
10092 lastentrance_dmap = tLastEntranceDMap;
10093 game->set_continue_scrn(tContScr);
10094 game->set_continue_dmap(tContDMap);
10095 x = tx;
10096 y = ty;
10097 z = tz;
10098 game->portalsrcdmap = tPortalDMap;
10099 FFCore.warp_player(wtIWARP, sourcedmap, sourcescr, -1, -1, mirror.misc1,
10100 mirror.usesound, 0, -1);
10101 }
10102 else if(mirror.flags & ITEM_FLAG1) //Place portal!
10103 {
10104 //Place the portal
10105 game->set_portal(sourcedmap, destdmap, offscr, x.getZLong(), y.getZLong(), mirror.usesound, mirror.misc1, mirror.wpn);
10106 //Since it was placed after loading this screen, load the portal object now
10107 game->load_portal();
10108 //Don't immediately trigger the warp back
10109 can_mirror_portal = false;
10110
10111 //Set continue point
10112 if(currdmap != game->get_continue_dmap())
10113 {
10114 game->set_continue_scrn(DMaps[currdmap].cont + DMaps[currdmap].xoff);
10115 }
10116 game->set_continue_dmap(currdmap);
10117 lastentrance_dmap = currdmap;
10118 lastentrance = game->get_continue_scrn();
10119 }
10120 }
10121 }
10122
10123 1888 void HeroClass::handle_passive_buttons()
10124 {
10125 1888 do_liftglove(-1,true);
10126 1888 do_jump(-1,true);
10127 1888 }
10128
10129 static bool did_passive_jump = false;
10130 1888 bool HeroClass::do_jump(int32_t jumpid, bool passive)
10131 {
10132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(passive) did_passive_jump = false;
10133 else if(did_passive_jump) return false; //don't jump twice in the same frame
10134
10135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(jumpid < 0)
10136 1888 jumpid = current_item_id(itype_rocs,true,true);
10137
10138
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(unsigned(jumpid) >= MAXITEMS) return false;
10139 if(inlikelike || charging) return false;
10140 if(!checkitem_jinx(jumpid)) return false;
10141
10142 itemdata const& itm = itemsbuf[jumpid];
10143
10144 bool standing = isStanding(true);
10145 if(!(standing || extra_jump_count < itm.misc1)) return false;
10146 if(!(checkbunny(jumpid) && checkmagiccost(jumpid)))
10147 {
10148 if(QMisc.miscsfx[sfxERROR])
10149 sfx(QMisc.miscsfx[sfxERROR]);
10150 return false;
10151 }
10152
10153 byte intbtn = byte(itm.misc2&0xFF);
10154 if(passive)
10155 {
10156 if(!getIntBtnInput(intbtn, true, true, false, false, true))
10157 return false; //not pressed
10158 }
10159
10160 paymagiccost(jumpid);
10161
10162 if(!standing)
10163 {
10164 ++extra_jump_count;
10165 fall = 0;
10166 fakefall = 0;
10167 if(hoverclk > 0)
10168 hoverclk = -hoverclk;
10169 }
10170 if(itm.flags & ITEM_FLAG1)
10171 setFall(fall - itm.power);
10172 else setFall(fall - (FEATHERJUMP*(itm.power+2)));
10173
10174 setOnSideviewLadder(false);
10175
10176 // Reset the ladder, unless on an unwalkable combo
10177 if((ladderx || laddery) && !(_walkflag(ladderx,laddery,0,SWITCHBLOCK_STATE)))
10178 reset_ladder();
10179
10180 if(itm.usesound)
10181 sfx(itm.usesound,pan(x.getInt()));
10182
10183 if(passive) did_passive_jump = true;
10184 return true;
10185 1888 }
10186 void HeroClass::drop_liftwpn()
10187 {
10188 if(!lift_wpn) return;
10189
10190 handle_lift(false); //sets position properly, accounting for large weapons
10191 auto liftid = current_item_id(itype_liftglove,true,true);
10192 itemdata const& glove = itemsbuf[liftid];
10193 if(glove.flags & ITEM_FLAG1)
10194 {
10195 lift_wpn->z = 0;
10196 lift_wpn->fakez = liftheight;
10197 }
10198 else lift_wpn->z = liftheight;
10199 lift_wpn->dir = dir;
10200 lift_wpn->step = 0;
10201 lift_wpn->fakefall = 0;
10202 lift_wpn->fall = 0;
10203 if(glove.flags & ITEM_FLAG1)
10204 lift_wpn->moveflags |= FLAG_NO_REAL_Z;
10205 else
10206 lift_wpn->moveflags |= FLAG_NO_FAKE_Z;
10207 Lwpns.add(lift_wpn);
10208 lift_wpn = nullptr;
10209 }
10210 1888 void HeroClass::do_liftglove(int32_t liftid, bool passive)
10211 {
10212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(liftid < 0)
10213 1888 liftid = current_item_id(itype_liftglove,true,true);
10214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(!can_lift(liftid)) return;
10215 itemdata const& glove = itemsbuf[liftid];
10216 byte intbtn = byte(glove.misc1&0xFF);
10217 if(passive)
10218 {
10219 if(!getIntBtnInput(intbtn, true, true, false, false, true))
10220 return; //not pressed
10221 }
10222
10223 bool had_weapon = lift_wpn;
10224
10225 if(!(had_weapon || //Allow throwing while bunnied/don't charge magic for throwing
10226 (checkbunny(liftid) && checkmagiccost(liftid))))
10227 {
10228 if(QMisc.miscsfx[sfxERROR])
10229 sfx(QMisc.miscsfx[sfxERROR]);
10230 return;
10231 }
10232 if(glove.script!=0 && (item_doscript[liftid] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)))
10233 return;
10234
10235 bool paidmagic = had_weapon; //don't pay to throw, only to lift
10236 if(glove.script)
10237 {
10238 if(!paidmagic)
10239 {
10240 paidmagic = true;
10241 paymagiccost(liftid);
10242 }
10243
10244 ri = &(itemScriptData[liftid]);
10245 for ( int32_t q = 0; q < 1024; q++ )
10246 item_stack[liftid][q] = 0xFFFF;
10247 ri->Clear();
10248 item_doscript[liftid] = 1;
10249 itemscriptInitialised[liftid] = 0;
10250 ZScriptVersion::RunScript(SCRIPT_ITEM, glove.script, liftid);
10251
10252 bool has_weapon = lift_wpn;
10253 if(has_weapon != had_weapon) //Item action script changed the lift information
10254 {
10255 if(passive)
10256 {
10257 getIntBtnInput(intbtn, true, true, false, false, false); //eat buttons
10258 }
10259 return;
10260 }
10261 }
10262
10263 if(lift_wpn)
10264 {
10265 if(!paidmagic)
10266 {
10267 paidmagic = true;
10268 paymagiccost(liftid);
10269 }
10270 if(!liftclk)
10271 {
10272 //Throw the weapon!
10273 //hero's direction and position
10274 handle_lift(false); //sets position properly, accounting for large weapons
10275 if(glove.flags & ITEM_FLAG1)
10276 {
10277 lift_wpn->z = 0;
10278 lift_wpn->fakez = liftheight;
10279 }
10280 else lift_wpn->z = liftheight;
10281 lift_wpn->dir = dir;
10282 //Configured throw speed in both axes
10283 lift_wpn->step = zfix(glove.misc2)/100;
10284 if(glove.flags & ITEM_FLAG1)
10285 {
10286 lift_wpn->fakefall = -glove.misc3;
10287 lift_wpn->moveflags |= FLAG_NO_REAL_Z;
10288 }
10289 else
10290 {
10291 lift_wpn->fall = -glove.misc3;
10292 lift_wpn->moveflags |= FLAG_NO_FAKE_Z;
10293 }
10294 Lwpns.add(lift_wpn);
10295 lift_wpn = nullptr;
10296 if(glove.usesound2)
10297 sfx(glove.usesound2,pan(int32_t(x)));
10298 }
10299
10300 if(passive)
10301 {
10302 getIntBtnInput(intbtn, true, true, false, false, false); //eat buttons
10303 }
10304 return;
10305 }
10306
10307 //Check for a liftable combo
10308 zfix bx, by;
10309 zfix bx2, by2;
10310 switch(dir)
10311 {
10312 case up:
10313 by = y + (bigHitbox ? -2 : 6);
10314 by2 = by;
10315 bx = x + 4;
10316 bx2 = bx + 8;
10317 break;
10318 case down:
10319 by = y + 17;
10320 by2 = by;
10321 bx = x + 4;
10322 bx2 = bx + 8;
10323 break;
10324 case left:
10325 by = y + (bigHitbox ? 0 : 8);
10326 by2 = y + 8;
10327 bx = x - 2;
10328 bx2 = x - 2;
10329 break;
10330 case right:
10331 by = y + (bigHitbox ? 0 : 8);
10332 by2 = y + 8;
10333 bx = x + 17;
10334 bx2 = x + 17;
10335 break;
10336 }
10337 int32_t pos = COMBOPOS_B(bx,by);
10338 int32_t pos2 = COMBOPOS_B(bx2,by2);
10339 int32_t foundpos = -1;
10340
10341 bool lifted = false;
10342 for(auto lyr = 6; lyr >= 0; --lyr)
10343 {
10344 mapscr* scr = FFCore.tempScreens[lyr];
10345 if(pos > -1)
10346 {
10347 newcombo const& cmb = combobuf[scr->data[pos]];
10348 if(cmb.liftflags & LF_LIFTABLE)
10349 {
10350 if(do_lift_combo(lyr,pos,liftid))
10351 {
10352 lifted = true;
10353 break;
10354 }
10355 }
10356 }
10357 if(pos != pos2 && pos2 > -1)
10358 {
10359 newcombo const& cmb2 = combobuf[scr->data[pos2]];
10360 if(cmb2.liftflags & LF_LIFTABLE)
10361 {
10362 if(do_lift_combo(lyr,pos2,liftid))
10363 {
10364 lifted = true;
10365 break;
10366 }
10367 }
10368 }
10369 }
10370 if(!lifted) return;
10371 if(!paidmagic)
10372 {
10373 paidmagic = true;
10374 paymagiccost(liftid);
10375 }
10376 if(passive)
10377 {
10378 getIntBtnInput(intbtn, true, true, false, false, false); //eat buttons
10379 }
10380 return;
10381 1888 }
10382 void HeroClass::handle_lift(bool dec)
10383 {
10384 lift_wpn->fakez = 0;
10385 if(!lift_wpn) liftclk = 0;
10386 if(liftclk <= (dec?1:0))
10387 {
10388 liftclk = 0;
10389 tliftclk = 0;
10390 if(lift_wpn)
10391 {
10392 if(lift_wpn->txsz > 1 || lift_wpn->tysz > 1)
10393 {
10394 lift_wpn->x = x+8 - (lift_wpn->txsz*8);
10395 lift_wpn->y = y+8 - (lift_wpn->tysz*8);
10396 }
10397 else
10398 {
10399 lift_wpn->x = x;
10400 lift_wpn->y = y;
10401 }
10402 lift_wpn->z = liftheight;
10403 }
10404 if(action == lifting)
10405 {
10406 action = none; FFCore.setHeroAction(none);
10407 }
10408 return;
10409 }
10410 if(dec) --liftclk;
10411 double xdist, ydist;
10412 double perc = (liftclk/double(tliftclk));
10413 switch(dir)
10414 {
10415 case up:
10416 {
10417 xdist = 0;
10418 ydist = -16;
10419 if(lift_wpn->txsz > 1)
10420 {
10421 xdist = -((lift_wpn->txsz*8)-8);
10422 }
10423 else xdist = 0;
10424 if(lift_wpn->tysz > 1)
10425 {
10426 ydist = -(lift_wpn->tysz*16);
10427 }
10428 ydist *= perc;
10429 break;
10430 }
10431 case down:
10432 {
10433 xdist = 0;
10434 ydist = 16;
10435 if(lift_wpn->txsz > 1)
10436 {
10437 xdist = -((lift_wpn->txsz*8)-8);
10438 }
10439 else xdist = 0;
10440 ydist *= perc;
10441 break;
10442 }
10443 case left:
10444 {
10445 xdist = -16;
10446 ydist = 0;
10447 if(lift_wpn->txsz > 1)
10448 {
10449 xdist = -(lift_wpn->txsz*16);
10450 }
10451 if(lift_wpn->tysz > 1)
10452 {
10453 ydist = -((lift_wpn->tysz*8)-8);
10454 }
10455 else ydist = 0;
10456 xdist *= perc;
10457 break;
10458 }
10459 case right:
10460 {
10461 xdist = 16;
10462 ydist = 0;
10463 if(lift_wpn->tysz > 1)
10464 {
10465 ydist = -((lift_wpn->tysz*8)-8);
10466 }
10467 else ydist = 0;
10468 xdist *= perc;
10469 break;
10470 }
10471 }
10472
10473 lift_wpn->x = x + xdist;
10474 lift_wpn->y = y + ydist;
10475 lift_wpn->z = liftheight*(1.0-perc);
10476 }
10477 1888 bool HeroClass::can_lift(int32_t gloveid)
10478 {
10479
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(unsigned(gloveid) >= MAXITEMS) return false;
10480 if(lstunclock) return false;
10481 if(!checkitem_jinx(gloveid)) return false;
10482 itemdata const& glove = itemsbuf[gloveid];
10483 switch(action)
10484 {
10485 case none: case walking:
10486 break;
10487
10488 case swimming:
10489 if(glove.flags & ITEM_FLAG2)
10490 break;
10491 return false;
10492
10493 default:
10494 return false;
10495 }
10496 return true;
10497 1888 }
10498 void HeroClass::lift(weapon* w, byte timer, zfix height)
10499 {
10500 lift_wpn = w;
10501 liftclk = timer;
10502 tliftclk = timer;
10503 if(height < 0)
10504 liftheight = 0;
10505 else liftheight = height;
10506 }
10507
10508 void HeroClass::doSwitchHook(byte style)
10509 {
10510 hs_switcher = true;
10511 pull_hero = true;
10512 //{ Load hook weapons, set them to obey special drawing
10513 weapon *w = (weapon*)Lwpns.spr(Lwpns.idFirst(wHookshot)),
10514 *hw = (weapon*)Lwpns.spr(Lwpns.idFirst(wHSHandle));
10515
10516 if(w)
10517 w->switch_hooked = true;
10518 if(hw)
10519 hw->switch_hooked = true;
10520 for(int32_t j=0; j<chainlinks.Count(); j++)
10521 {
10522 chainlinks.spr(j)->switch_hooked = true;
10523 }
10524 //}
10525 if(hooked_combopos > -1)
10526 {
10527 int32_t max_layer = get_bit(quest_rules, qr_HOOKSHOTALLLAYER) ? 6 : (get_bit(quest_rules, qr_HOOKSHOTLAYERFIX) ? 2 : 0);
10528 hooked_layerbits = 0;
10529 for(auto q = 0; q < 7; ++q)
10530 hooked_undercombos[q] = -1;
10531 uint16_t plpos = COMBOPOS(x+8,y+8);
10532 for(auto q = max_layer; q > -1; --q)
10533 {
10534 newcombo const& cmb = combobuf[FFCore.tempScreens[q]->data[hooked_combopos]];
10535 newcombo const& comb2 = combobuf[FFCore.tempScreens[q]->data[plpos]];
10536 int32_t fl1 = FFCore.tempScreens[q]->sflag[hooked_combopos],
10537 fl2 = FFCore.tempScreens[q]->sflag[plpos];
10538 bool isPush = false;
10539 if(isSwitchHookable(cmb))
10540 {
10541 if(cmb.type == cSWITCHHOOK)
10542 {
10543 uint16_t plpos = COMBOPOS(x+8,y+8);
10544 if((cmb.usrflags&cflag1) && FFCore.tempScreens[q]->data[plpos])
10545 continue; //don't swap with non-zero combo
10546 if(zc_max(1,itemsbuf[(w && w->parentitem>-1) ? w->parentitem : current_item_id(itype_switchhook)].fam_type) < cmb.attribytes[0])
10547 continue; //too low a switchhook level
10548 hooked_layerbits |= 1<<q; //Swapping
10549 if(cmb.usrflags&cflag3)
10550 {
10551 if(cmb.usrflags&cflag6)
10552 {
10553 hooked_undercombos[q] = FFCore.tempScreens[q]->data[hooked_combopos]+1;
10554 hooked_undercombos[q+7] = FFCore.tempScreens[q]->cset[hooked_combopos];
10555 }
10556 else
10557 {
10558 hooked_undercombos[q] = FFCore.tempScreens[q]->undercombo;
10559 hooked_undercombos[q+7] = FFCore.tempScreens[q]->undercset;
10560 }
10561 }
10562 else
10563 {
10564 hooked_layerbits |= 1<<(q+8); //Swapping BACK
10565 if(cmb.usrflags&cflag7) //counts as 'pushblock'
10566 isPush = true;
10567 }
10568 }
10569 else if(isCuttableType(cmb.type))
10570 {
10571 if(isCuttableNextType(cmb.type))
10572 {
10573 hooked_undercombos[q] = FFCore.tempScreens[q]->data[hooked_combopos]+1;
10574 hooked_undercombos[q+7] = FFCore.tempScreens[q]->cset[hooked_combopos];
10575 }
10576 else
10577 {
10578 hooked_undercombos[q] = FFCore.tempScreens[q]->undercombo;
10579 hooked_undercombos[q+7] = FFCore.tempScreens[q]->undercset;
10580 }
10581 hooked_layerbits |= 1<<q; //Swapping
10582 }
10583 else
10584 {
10585 hooked_layerbits |= 1<<q; //Swapping
10586 hooked_layerbits |= 1<<(q+8); //Swapping BACK
10587 }
10588 }
10589 if(hooked_layerbits & (1<<(q+8))) //2-way swap, check for pushblocks
10590 {
10591 if((cmb.type==cPUSH_WAIT || cmb.type==cPUSH_HW || cmb.type==cPUSH_HW2)
10592 && hasMainGuy())
10593 {
10594 hooked_layerbits &= ~(0x101<<q); //Can't swap yet
10595 continue;
10596 }
10597 if(fl1 == mfPUSHED)
10598 {
10599 hooked_layerbits &= ~(0x101<<q); //Can't swap at all, locked in place
10600 continue;
10601 }
10602 if(!isPush) switch(fl1)
10603 {
10604 case mfPUSHUD: case mfPUSHUDNS: case mfPUSHUDINS:
10605 case mfPUSHLR: case mfPUSHLRNS: case mfPUSHLRINS:
10606 case mfPUSHU: case mfPUSHUNS: case mfPUSHUINS:
10607 case mfPUSHD: case mfPUSHDNS: case mfPUSHDINS:
10608 case mfPUSHL: case mfPUSHLNS: case mfPUSHLINS:
10609 case mfPUSHR: case mfPUSHRNS: case mfPUSHRINS:
10610 case mfPUSH4: case mfPUSH4NS: case mfPUSH4INS:
10611 isPush = true;
10612 }
10613 if(!isPush) switch(cmb.flag)
10614 {
10615 case mfPUSHUD: case mfPUSHUDNS: case mfPUSHUDINS:
10616 case mfPUSHLR: case mfPUSHLRNS: case mfPUSHLRINS:
10617 case mfPUSHU: case mfPUSHUNS: case mfPUSHUINS:
10618 case mfPUSHD: case mfPUSHDNS: case mfPUSHDINS:
10619 case mfPUSHL: case mfPUSHLNS: case mfPUSHLINS:
10620 case mfPUSHR: case mfPUSHRNS: case mfPUSHRINS:
10621 case mfPUSH4: case mfPUSH4NS: case mfPUSH4INS:
10622 isPush = true;
10623 }
10624 if(isPush) //Check for block holes / triggers
10625 {
10626 if(comb2.flag == mfBLOCKHOLE || fl2 == mfBLOCKHOLE
10627 || comb2.flag == mfBLOCKTRIGGER || fl2 == mfBLOCKTRIGGER)
10628 {
10629 hooked_layerbits &= ~(1<<(q+8)); //Don't swap the hole/trigger back
10630 }
10631 else if(!get_bit(quest_rules, qr_BLOCKHOLE_SAME_ONLY))
10632 {
10633 auto maxLayer = get_bit(quest_rules, qr_PUSHBLOCK_LAYER_1_2) ? 2 : 0;
10634 for(auto lyr = 0; lyr < maxLayer; ++lyr)
10635 {
10636 if(lyr == q) continue;
10637 switch(FFCore.tempScreens[q]->sflag[plpos])
10638 {
10639 case mfBLOCKHOLE: case mfBLOCKTRIGGER:
10640 hooked_layerbits &= ~(1<<(q+8)); //Don't swap the hole/trigger back
10641 lyr=7;
10642 break;
10643 }
10644 switch(combobuf[FFCore.tempScreens[q]->data[plpos]].flag)
10645 {
10646 case mfBLOCKHOLE: case mfBLOCKTRIGGER:
10647 hooked_layerbits &= ~(1<<(q+8)); //Don't swap the hole/trigger back
10648 lyr=7;
10649 break;
10650 }
10651 }
10652 }
10653 }
10654 }
10655 }
10656 }
10657 switch_hooked = true;
10658 switchhookstyle = style;
10659 switch(style)
10660 {
10661 default: case swPOOF:
10662 {
10663 wpndata const& spr = wpnsbuf[QMisc.sprites[sprSWITCHPOOF]];
10664 switchhookmaxtime = switchhookclk = zc_max(spr.frames,1) * zc_max(spr.speed,1);
10665 decorations.add(new comboSprite(x, y, 0, 0, QMisc.sprites[sprSWITCHPOOF]));
10666 if(hooked_combopos > -1)
10667 decorations.add(new comboSprite((zfix)COMBOX(hooked_combopos), (zfix)COMBOY(hooked_combopos), 0, 0, QMisc.sprites[sprSWITCHPOOF]));
10668 else if(switching_object)
10669 decorations.add(new comboSprite(switching_object->x, switching_object->y, 0, 0, QMisc.sprites[sprSWITCHPOOF]));
10670 break;
10671 }
10672 case swFLICKER:
10673 {
10674 switchhookmaxtime = switchhookclk = 64;
10675 break;
10676 }
10677 case swRISE:
10678 {
10679 switchhookmaxtime = switchhookclk = 64;
10680 break;
10681 }
10682 }
10683 }
10684
10685 17 bool HeroClass::startwpn(int32_t itemid)
10686 {
10687
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if(itemid < 0) return false;
10688 17 itemdata const& itm = itemsbuf[itemid];
10689
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
17 if(((dir==up && y<24) || (dir==down && y>128) ||
10690
4/6
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
17 (dir==left && x<32) || (dir==right && x>208)) && !(get_bit(quest_rules,qr_ITEMSONEDGES) || inlikelike))
10691 return false;
10692
10693 17 int32_t wx=x;
10694 17 int32_t wy=y-fakez;
10695 17 int32_t wz=z;
10696 17 bool ret = true;
10697
10698
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 7 times.
17 switch(dir)
10699 {
10700 case up:
10701 2 wy-=16;
10702 2 break;
10703
10704 case down:
10705 1 wy+=16;
10706 1 break;
10707
10708 case left:
10709 7 wx-=16;
10710 7 break;
10711
10712 case right:
10713 7 wx+=16;
10714 7 break;
10715 }
10716
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
17 if (IsSideSwim() && (itm.flags & ITEM_SIDESWIM_DISABLED)) return false;
10717
10718
1/27
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 17 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
17 switch(itm.family)
10719 {
10720 case itype_liftglove:
10721 {
10722 do_liftglove(itemid,false);
10723 dowpn = -1;
10724 ret = false;
10725 break;
10726 }
10727 case itype_potion:
10728 {
10729 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
10730 {
10731 if(QMisc.miscsfx[sfxERROR])
10732 sfx(QMisc.miscsfx[sfxERROR]);
10733 return false;
10734 }
10735
10736 paymagiccost(itemid);
10737
10738 if(itm.misc1 || itm.misc2)
10739 {
10740 refill_what=REFILL_ALL;
10741 refill_why=itemid;
10742 StartRefill(REFILL_ALL);
10743 potion_life = game->get_life();
10744 potion_magic = game->get_magic();
10745
10746 //add a quest rule or an item option that lets you specify whether or not to pause music during refilling
10747 //music_pause();
10748 stop_sfx(QMisc.miscsfx[sfxLOWHEART]); //stop heart beep!
10749 while(refill())
10750 {
10751 do_refill_waitframe();
10752 }
10753
10754 //add a quest rule or an item option that lets you specify whether or not to pause music during refilling
10755 //music_resume();
10756 ret = false;
10757 }
10758
10759 break;
10760 }
10761 case itype_bottle:
10762 {
10763 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
10764 {
10765 if(QMisc.miscsfx[sfxERROR])
10766 sfx(QMisc.miscsfx[sfxERROR]);
10767 return false;
10768 }
10769 if(itm.script!=0 && (item_doscript[itemid] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)))
10770 return false;
10771
10772 size_t bind = game->get_bottle_slot(itm.misc1);
10773 bool paidmagic = false;
10774 if(itm.script)
10775 {
10776 paidmagic = true;
10777 paymagiccost(itemid);
10778
10779 ri = &(itemScriptData[itemid]);
10780 for ( int32_t q = 0; q < 1024; q++ )
10781 item_stack[itemid][q] = 0xFFFF;
10782 ri->Clear();
10783 item_doscript[itemid] = 1;
10784 itemscriptInitialised[itemid] = 0;
10785 ZScriptVersion::RunScript(SCRIPT_ITEM, itm.script, itemid);
10786 bind = game->get_bottle_slot(itm.misc1);
10787 }
10788 bottletype const* bt = bind ? &(QMisc.bottle_types[bind-1]) : NULL;
10789 if(bt)
10790 {
10791 word toFill[3] = { 0 };
10792 for(size_t q = 0; q < 3; ++q)
10793 {
10794 char c = bt->counter[q];
10795 if(c > -1)
10796 {
10797 if(bt->flags & (1<<q))
10798 {
10799 toFill[q] = (bt->amount[q]==100)
10800 ? game->get_maxcounter(c)
10801 : word((game->get_maxcounter(c)/100.0)*bt->amount[q]);
10802 }
10803 else toFill[q] = bt->amount[q];
10804 if(toFill[q] + game->get_counter(c) > game->get_maxcounter(c))
10805 {
10806 toFill[q] = game->get_maxcounter(c) - game->get_counter(c);
10807 }
10808 }
10809 }
10810 word max = std::max(toFill[0], std::max(toFill[1], toFill[2]));
10811 bool run = max > 0;
10812 if(get_bit(quest_rules, qr_NO_BOTTLE_IF_ANY_COUNTER_FULL))
10813 run = ((bt->counter[0] > -1 && !toFill[0]) || (bt->counter[1] > -1 && !toFill[1]) || (bt->counter[2] > -1 && !toFill[2]));
10814 else
10815 {
10816 if((bt->flags & BTFLAG_CURESWJINX) && swordclk)
10817 run = true;
10818 else if((bt->flags & BTFLAG_CUREITJINX) && itemclk)
10819 run = true;
10820 }
10821 if(run || (bt->flags&BTFLAG_ALLOWIFFULL))
10822 {
10823 if(bt->flags & BTFLAG_CURESWJINX)
10824 {
10825 swordclk = 0;
10826 verifyAWpn();
10827 }
10828 if(bt->flags & BTFLAG_CUREITJINX)
10829 itemclk = 0;
10830 if(!paidmagic)
10831 paymagiccost(itemid);
10832 stop_sfx(QMisc.miscsfx[sfxLOWHEART]); //stop heart beep!
10833 sfx(itm.usesound,pan(x.getInt()));
10834 for(size_t q = 0; q < 20; ++q)
10835 do_refill_waitframe();
10836 double inc = max/60.0; //1 second
10837 double xtra[3]{ 0 };
10838 for(size_t q = 0; q < 60; ++q)
10839 {
10840 if(!(q%6) && (toFill[0]||toFill[1]||toFill[2]))
10841 sfx(QMisc.miscsfx[sfxREFILL]);
10842 for(size_t j = 0; j < 3; ++j)
10843 {
10844 xtra[j] += inc;
10845 word f = floor(xtra[j]);
10846 xtra[j] -= f;
10847 if(toFill[j] > f)
10848 {
10849 toFill[j] -= f;
10850 game->change_counter(f,bt->counter[j]);
10851 }
10852 else if(toFill[j])
10853 {
10854 game->change_counter(toFill[j],bt->counter[j]);
10855 toFill[j] = 0;
10856 }
10857 }
10858 do_refill_waitframe();
10859 }
10860 for(size_t j = 0; j < 3; ++j)
10861 {
10862 if(toFill[j])
10863 {
10864 game->change_counter(toFill[j],bt->counter[j]);
10865 toFill[j] = 0;
10866 }
10867 }
10868 for(size_t q = 0; q < 20; ++q)
10869 do_refill_waitframe();
10870 game->set_bottle_slot(itm.misc1, bt->next_type);
10871 }
10872 }
10873
10874 dowpn = -1;
10875 ret = false;
10876 break;
10877 }
10878
10879 case itype_note:
10880 {
10881 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
10882 {
10883 if(QMisc.miscsfx[sfxERROR])
10884 sfx(QMisc.miscsfx[sfxERROR]);
10885 return false;
10886 }
10887 if(!msg_active && itm.misc1 > 0 && itm.misc1 < MAXMSGS)
10888 {
10889 sfx(itm.usesound);
10890 donewmsg(itm.misc1);
10891 paymagiccost(itemid);
10892 }
10893 dowpn = -1;
10894 ret = false;
10895 break;
10896 }
10897
10898 case itype_mirror:
10899 doMirror(itemid);
10900 if(Quit)
10901 return false;
10902 ret = false;
10903 break;
10904
10905 case itype_rocs:
10906 {
10907 if(!do_jump(itemid,false)) return false;
10908 ret = false;
10909 }
10910 break;
10911
10912 case itype_letter:
10913 {
10914 if(current_item(itype_letter)==i_letter &&
10915 tmpscr[currscr<128?0:1].room==rP_SHOP &&
10916 tmpscr[currscr<128?0:1].guy &&
10917 ((currscr<128&&!(DMaps[currdmap].flags&dmfGUYCAVES))
10918 ||(currscr>=128&&DMaps[currdmap].flags&dmfGUYCAVES)) &&
10919 checkbunny(itemid)
10920 )
10921 {
10922 int32_t usedid = getItemID(itemsbuf, itype_letter,i_letter+1);
10923
10924 if(usedid != -1)
10925 getitem(usedid, true, true);
10926
10927 sfx(tmpscr[currscr<128?0:1].secretsfx);
10928 setupscreen();
10929 action=none; FFCore.setHeroAction(none);
10930 }
10931
10932 ret = false;
10933 }
10934 break;
10935
10936 case itype_whistle:
10937 {
10938 bool whistleflag;
10939
10940 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
10941 {
10942 if(QMisc.miscsfx[sfxERROR])
10943 sfx(QMisc.miscsfx[sfxERROR]);
10944 return false;
10945 }
10946
10947 paymagiccost(itemid);
10948 sfx(itm.usesound);
10949
10950 if(dir==up || dir==right)
10951 ++blowcnt;
10952 else
10953 --blowcnt;
10954
10955 int sfx_count = 0;
10956 while ((!replay_is_active() && sfx_allocated(itm.usesound)) || (replay_is_active() && sfx_count < 180))
10957 {
10958 sfx_count += 1;
10959 advanceframe(true);
10960
10961 if(Quit)
10962 return false;
10963 }
10964
10965 Lwpns.add(new weapon(x,y-fakez,z,wWhistle,0,0,dir,itemid,getUID(),false,0,1,0));
10966
10967 if((whistleflag=findentrance(x,y,mfWHISTLE,get_bit(quest_rules, qr_PERMANENT_WHISTLE_SECRETS))))
10968 didstuff |= did_whistle;
10969
10970 if((didstuff&did_whistle && itm.flags&ITEM_FLAG1) || currscr>=128)
10971 return false;
10972
10973 if(itm.flags&ITEM_FLAG1) didstuff |= did_whistle;
10974
10975 if((tmpscr->flags&fWHISTLE) || (tmpscr->flags7 & fWHISTLEWATER)
10976 || (tmpscr->flags7&fWHISTLEPAL))
10977 {
10978 whistleclk=0; // signal to start drying lake or doing other stuff
10979 }
10980 else
10981 {
10982 int32_t where = itm.misc1;
10983
10984 if(where>right) where=dir^1;
10985
10986 if(((DMaps[currdmap].flags&dmfWHIRLWIND && TriforceCount()) || DMaps[currdmap].flags&dmfWHIRLWINDRET) &&
10987 itm.misc2 >= 0 && itm.misc2 <= 8 && !whistleflag)
10988 Lwpns.add(new weapon((zfix)(where==left?zfix(240):where==right?zfix(0):x),
10989 (zfix)(where==down?zfix(0):where==up?zfix(160):y),
10990 (zfix)0,
10991 wWind,
10992 0, //type
10993 0,
10994 where,
10995 itemid,getUID(),false,false,true,0)); //last arg is byte special, used to override type for wWind for now. -Z 18JULY2020
10996
10997 whistleitem=itemid;
10998 }
10999
11000 ret = false;
11001 }
11002 break;
11003
11004 case itype_bomb:
11005 {
11006 //Remote detonation
11007 if(Lwpns.idCount(wLitBomb) >= zc_max(itm.misc2,1))
11008 {
11009 weapon *ew = (weapon*)(Lwpns.spr(Lwpns.idFirst(wLitBomb)));
11010
11011 while(Lwpns.idCount(wLitBomb) && ew->misc == 0)
11012 {
11013 //If this ever needs a version check, in the future. -z
11014 if ( FFCore.getQuestHeaderInfo(vZelda) > 0x250 || ( FFCore.getQuestHeaderInfo(vZelda) == 0x250 && FFCore.getQuestHeaderInfo(vBuild) > 31 ) )
11015 {
11016 if ( ew->power > 1 ) //Don't reduce 1 to 0. -Z
11017 ew->power *= 0.5; //Remote bombs were dealing double damage. -Z
11018 }
11019 ew->misc=50;
11020 ew->clk=ew->misc-3;
11021 ew->id=wBomb;
11022 ew = (weapon*)(Lwpns.spr(Lwpns.idFirst(wLitBomb)));
11023 }
11024
11025 deselectbombs(false);
11026 return false;
11027 }
11028
11029 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11030 {
11031 if(QMisc.miscsfx[sfxERROR])
11032 sfx(QMisc.miscsfx[sfxERROR]);
11033 return false;
11034 }
11035
11036 paymagiccost(itemid);
11037
11038 if(itm.misc1>0) // If not remote bombs
11039 deselectbombs(false);
11040
11041 if(isdungeon())
11042 {
11043 wy=zc_max(wy,16);
11044 }
11045
11046 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wLitBomb,itm.fam_type,
11047 itm.power*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11048 sfx(WAV_PLACE,pan(wx));
11049 }
11050 break;
11051
11052 case itype_sbomb:
11053 {
11054 //Remote detonation
11055 if(Lwpns.idCount(wLitSBomb) >= zc_max(itm.misc2,1))
11056 {
11057 weapon *ew = (weapon*)(Lwpns.spr(Lwpns.idFirst(wLitSBomb)));
11058
11059 while(Lwpns.idCount(wLitSBomb) && ew->misc == 0)
11060 {
11061 ew->misc=50;
11062 ew->clk=ew->misc-3;
11063 ew->id=wSBomb;
11064 ew = (weapon*)(Lwpns.spr(Lwpns.idFirst(wLitSBomb)));
11065 }
11066
11067 deselectbombs(true);
11068 return false;
11069 }
11070
11071 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11072 {
11073 if(QMisc.miscsfx[sfxERROR])
11074 sfx(QMisc.miscsfx[sfxERROR]);
11075 return false;
11076 }
11077
11078 paymagiccost(itemid);
11079
11080 if(itm.misc1>0) // If not remote bombs
11081 deselectbombs(true);
11082
11083 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wLitSBomb,itm.fam_type,itm.power*game->get_hero_dmgmult(),dir, itemid,getUID(),false,false,true));
11084 sfx(WAV_PLACE,pan(wx));
11085 }
11086 break;
11087
11088 case itype_wand:
11089 {
11090 if(Lwpns.idCount(wMagic))
11091 {
11092 misc_internal_hero_flags &= ~LF_PAID_WAND_COST;
11093 return false;
11094 }
11095
11096 int32_t bookid = current_item_id(itype_book);
11097 bool paybook = (bookid>-1 && checkbunny(bookid) && checkmagiccost(bookid));
11098
11099 if(!(itm.flags&ITEM_FLAG1) && !paybook) //Can the wand shoot without the book?
11100 {
11101 misc_internal_hero_flags &= ~LF_PAID_WAND_COST;
11102 return false;
11103 }
11104
11105 if(!checkbunny(itemid) || !(misc_internal_hero_flags & LF_PAID_WAND_COST || checkmagiccost(itemid)))
11106 {
11107 if(QMisc.miscsfx[sfxERROR])
11108 sfx(QMisc.miscsfx[sfxERROR]);
11109 return false;
11110 }
11111
11112 if(Lwpns.idCount(wBeam))
11113 Lwpns.del(Lwpns.idFirst(wBeam));
11114
11115 int32_t type, pow;
11116 if ( get_bit(quest_rules,qr_BROKENBOOKCOST) )
11117 {
11118 type = bookid != -1 ? current_item(itype_book) : itm.fam_type;
11119 pow = (bookid != -1 ? current_item_power(itype_book) : itm.power)*game->get_hero_dmgmult();
11120 }
11121 else
11122 {
11123 type = (bookid != -1 && paybook) ? current_item(itype_book) : itm.fam_type;
11124 pow = ((bookid != -1 && paybook) ? current_item_power(itype_book) : itm.power)*game->get_hero_dmgmult();
11125 }
11126 for(int32_t i=(spins==1?up:dir); i<=(spins==1 ? right:dir); i++)
11127 if(dir!=(i^1))
11128 {
11129 weapon *magic = new weapon((zfix)wx,(zfix)wy,(zfix)wz,wMagic,type,pow,i, itemid,getUID(),false,false,true);
11130 if(paybook)
11131 magic->linkedItem = bookid;
11132 //magic->dir = this->dir; //Save player dir for special weapons.
11133 Lwpns.add(magic);
11134 }
11135 if(!(misc_internal_hero_flags & LF_PAID_WAND_COST))
11136 paymagiccost(itemid);
11137 else misc_internal_hero_flags &= ~LF_PAID_WAND_COST;
11138
11139 if(paybook)
11140 paymagiccost(current_item_id(itype_book));
11141
11142 if(bookid != -1)
11143 {
11144 if (( itemsbuf[bookid].flags & ITEM_FLAG4 ))
11145 {
11146 sfx(itemsbuf[bookid].misc2,pan(wx));
11147 }
11148 else
11149 {
11150 sfx(itm.usesound,pan(wx));
11151 }
11152 }
11153 else
11154 sfx(itm.usesound,pan(wx));
11155 }
11156 /*
11157 // Fireball Wand
11158 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wRefFireball,0,2*game->get_hero_dmgmult(),dir));
11159 switch (dir)
11160 {
11161 case up:
11162 Lwpns.spr(Lwpns.Count()-1)->angle=-PI/2;
11163 Lwpns.spr(Lwpns.Count()-1)->dir=up;
11164 break;
11165 case down:
11166 Lwpns.spr(Lwpns.Count()-1)->angle=PI/2;
11167 Lwpns.spr(Lwpns.Count()-1)->dir=down;
11168 break;
11169 case left:
11170 Lwpns.spr(Lwpns.Count()-1)->angle=PI;
11171 Lwpns.spr(Lwpns.Count()-1)->dir=left;
11172 break;
11173 case right:
11174 Lwpns.spr(Lwpns.Count()-1)->angle=0;
11175 Lwpns.spr(Lwpns.Count()-1)->dir=right;
11176 break;
11177 }
11178 Lwpns.spr(Lwpns.Count()-1)->clk=16;
11179 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->step=3.5;
11180 Lwpns.spr(Lwpns.Count()-1)->dummy_bool[0]=true; //homing
11181 */
11182 break;
11183
11184 case itype_sword:
11185 {
11186
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
17 if(!(checkbunny(itemid) || !(misc_internal_hero_flags & LF_PAID_SWORD_COST || checkmagiccost(itemid))))
11187 {
11188 if(QMisc.miscsfx[sfxERROR])
11189 sfx(QMisc.miscsfx[sfxERROR]);
11190 return false;
11191 }
11192
11193
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 12 times.
17 if((Lwpns.idCount(wBeam) && spins==0)||Lwpns.idCount(wMagic))
11194 {
11195 5 misc_internal_hero_flags &= ~LF_PAID_SWORD_COST;
11196 5 return false;
11197 }
11198
11199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(!(misc_internal_hero_flags & LF_PAID_SWORD_COST))//If already paid to use sword melee, don't charge again
11200 12 paymagiccost(itemid);
11201 else misc_internal_hero_flags &= ~LF_PAID_SWORD_COST;
11202 float temppower;
11203
11204
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if(itm.flags & ITEM_FLAG2)
11205 {
11206 12 temppower=game->get_hero_dmgmult()*itm.power;
11207 12 temppower=temppower*itm.misc2;
11208 12 temppower=temppower/100;
11209 12 }
11210 else
11211 {
11212 temppower = game->get_hero_dmgmult()*itm.misc2;
11213 }
11214
11215 //Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wBeam,itm.fam_type,int32_t(temppower),dir,itemid,getUID()));
11216 //Add weapon script to sword beams.
11217
5/10
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
12 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wBeam,itm.fam_type,int32_t(temppower),dir,itemid,getUID(),false,false,true));
11218 //weapon *w = (weapon*)Lwpns.spr(Lwpns.Count()-1); //the pointer to this beam
11219 //w->weaponscript = itm.weaponscript;
11220 //w->canrunscript = 0;
11221 12 sfx(WAV_BEAM,pan(wx));
11222 }
11223 12 break;
11224
11225 case itype_candle:
11226 {
11227 int32_t countid = itemid;
11228 if(get_bit(quest_rules, qr_CANDLES_SHARED_LIMIT))
11229 countid = -itype_candle;
11230 if(itm.flags&ITEM_FLAG1 && usecounts[countid] >= zc_max(1, itm.misc3))
11231 {
11232 return false;
11233 }
11234
11235 if(Lwpns.idCount(wFire) >= (itm.misc3 < 1 ? 2 : itm.misc3))
11236 {
11237 return false;
11238 }
11239
11240 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11241 {
11242 if(QMisc.miscsfx[sfxERROR])
11243 sfx(QMisc.miscsfx[sfxERROR]);
11244 return false;
11245 }
11246
11247 paymagiccost(itemid);
11248
11249 if(itm.flags&ITEM_FLAG1) ++usecounts[countid];
11250
11251 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wFire,
11252 //(itm.fam_type > 1), //To do with combo flags ... Needs to be changed to fix ->Level for wFire
11253 (itm.fam_type), //To do with combo flags ... Needs to be changed to fix ->Level for wFire
11254 itm.power*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11255 sfx(itm.usesound,pan(wx));
11256 attack=wFire;
11257 }
11258 break;
11259
11260 case itype_script1: case itype_script2: case itype_script3: case itype_script4: case itype_script5:
11261 case itype_script6: case itype_script7: case itype_script8: case itype_script9: case itype_script10:
11262 {
11263 int32_t wtype = wScript1 + (itm.family-itype_script1);
11264 if(Lwpns.idCount(wtype))
11265 return false;
11266
11267 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11268 {
11269 if(QMisc.miscsfx[sfxERROR])
11270 sfx(QMisc.miscsfx[sfxERROR]);
11271 return false;
11272 }
11273
11274 if(!get_bit(quest_rules, qr_CUSTOMWEAPON_IGNORE_COST))
11275 paymagiccost(itemid);
11276
11277 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wtype,itm.fam_type,game->get_hero_dmgmult()*itm.power,dir,itemid,getUID(),false,false,true));
11278 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->step = itm.misc1;
11279 sfx(itm.usesound,pan(wx));
11280 }
11281 break;
11282
11283 case itype_icerod:
11284 {
11285 if(Lwpns.idCount(wIce))
11286 return false;
11287
11288 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11289 {
11290 if(QMisc.miscsfx[sfxERROR])
11291 sfx(QMisc.miscsfx[sfxERROR]);
11292 return false;
11293 }
11294
11295 if(!get_bit(quest_rules, qr_CUSTOMWEAPON_IGNORE_COST))
11296 paymagiccost(itemid);
11297
11298 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wIce,itm.fam_type,game->get_hero_dmgmult()*itm.power,dir,itemid,getUID(),false,false,true));
11299 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->step = itm.misc1;
11300 sfx(itm.usesound,pan(wx));
11301 }
11302 break;
11303
11304 case itype_arrow:
11305 {
11306 if(Lwpns.idCount(wArrow) > itm.misc2)
11307 return false;
11308
11309 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11310 {
11311 if(QMisc.miscsfx[sfxERROR])
11312 sfx(QMisc.miscsfx[sfxERROR]);
11313 return false;
11314 }
11315
11316 paymagiccost(itemid);
11317
11318 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wArrow,itm.fam_type,game->get_hero_dmgmult()*itm.power,dir,itemid,getUID(),false,false,true));
11319 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->step*=(current_item_power(itype_bow)+1)/2;
11320 sfx(itm.usesound,pan(wx));
11321 }
11322 break;
11323
11324 case itype_bait:
11325 if(Lwpns.idCount(wBait)) //TODO: More than one Bait per screen?
11326 return false;
11327
11328 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11329 {
11330 if(QMisc.miscsfx[sfxERROR])
11331 sfx(QMisc.miscsfx[sfxERROR]);
11332 return false;
11333 }
11334
11335 paymagiccost(itemid);
11336 sfx(itm.usesound,pan(wx));
11337
11338 if(tmpscr->room==rGRUMBLE && (!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN)))
11339 {
11340 items.add(new item((zfix)wx,(zfix)wy,(zfix)0,iBait,ipDUMMY+ipFADE,0));
11341 fadeclk=66;
11342 dismissmsg();
11343 clear_bitmap(pricesdisplaybuf);
11344 set_clip_state(pricesdisplaybuf, 1);
11345 // putscr(scrollbuf,0,0,tmpscr);
11346 setmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM);
11347 removeItemsOfFamily(game,itemsbuf,itype_bait);
11348 verifyBothWeapons();
11349 sfx(tmpscr->secretsfx);
11350 return false;
11351 }
11352
11353 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wBait,0,0,dir,itemid,getUID(),false,false,true));
11354 break;
11355
11356 case itype_brang:
11357 {
11358 if(Lwpns.idCount(wBrang) > itm.misc2)
11359 return false;
11360
11361 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11362 {
11363 if(QMisc.miscsfx[sfxERROR])
11364 sfx(QMisc.miscsfx[sfxERROR]);
11365 return false;
11366 }
11367
11368 paymagiccost(itemid);
11369 current_item_power(itype_brang);
11370 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wBrang,itm.fam_type,(itm.power*game->get_hero_dmgmult()),dir,itemid,getUID(),false,false,true));
11371 }
11372 break;
11373
11374 case itype_hookshot:
11375 case itype_switchhook:
11376 {
11377 if(inlikelike || Lwpns.idCount(wHookshot))
11378 return false;
11379
11380 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11381 {
11382 if(QMisc.miscsfx[sfxERROR])
11383 sfx(QMisc.miscsfx[sfxERROR]);
11384 return false;
11385 }
11386 bool sw = itm.family == itype_switchhook;
11387
11388 if(sw && (itm.flags&ITEM_FLAG8))
11389 switchhook_cost_item = itemid;
11390 else paymagiccost(itemid);
11391
11392 bool use_hookshot=true;
11393 bool hit_hs = false, hit_solid = false, insta_switch = false;
11394 int32_t max_layer = get_bit(quest_rules, qr_HOOKSHOTALLLAYER) ? 6 : (get_bit(quest_rules, qr_HOOKSHOTLAYERFIX) ? 2 : 0);
11395 int32_t cpos = -1;
11396 for(int32_t i=0; i<=max_layer && !hit_hs; ++i)
11397 {
11398 if(dir==up)
11399 {
11400 cpos = check_hshot(i,x+2,y-7,sw);
11401 if(cpos > -1)
11402 hit_hs = true;
11403 }
11404 else if(dir==down)
11405 {
11406 cpos = check_hshot(i,x+12,y+23,sw);
11407 if(cpos > -1)
11408 hit_hs = true;
11409 }
11410 else if(dir==left)
11411 {
11412 cpos = check_hshot(i,x-7,y+12,sw);
11413 if(cpos > -1)
11414 hit_hs = true;
11415 }
11416 else if(dir==right)
11417 {
11418 cpos = check_hshot(i,x+23,y+12,sw);
11419 if(cpos > -1)
11420 hit_hs = true;
11421 }
11422 //Diagonal Hookshot (6)
11423 else if(dir==r_down)
11424 {
11425 cpos = check_hshot(i,x+9,y+13,sw);
11426 if(cpos > -1)
11427 hit_hs = true;
11428 }
11429 else if(dir==l_down)
11430 {
11431 cpos = check_hshot(i,x+6,y+13,sw);
11432 if(cpos > -1)
11433 hit_hs = true;
11434 }
11435 else if(dir==r_up)
11436 {
11437 cpos = check_hshot(i,x+9,y+13,sw);
11438 if(cpos > -1)
11439 hit_hs = true;
11440 }
11441 else if(dir==l_up)
11442 {
11443 cpos = check_hshot(i,x+6,y+13,sw);
11444 if(cpos > -1)
11445 hit_hs = true;
11446 }
11447 }
11448 if(dir==up && _walkflag(x+2,y+4,1,SWITCHBLOCK_STATE) && !ishookshottable(x.getInt(),int32_t(y+4)))
11449 hit_solid = true;
11450 if(hit_hs)
11451 {
11452 if(sw)
11453 insta_switch = true; //switch immediately
11454 else use_hookshot = false; //No hooking against grabbable
11455 }
11456 if(hit_solid && !insta_switch)
11457 use_hookshot = false;
11458 if(use_hookshot)
11459 {
11460 int32_t hookitem = itm.fam_type;
11461 int32_t hookpower = itm.power;
11462 byte allow_diagonal = (itm.flags & ITEM_FLAG2) ? 1 : 0;
11463
11464 if(!Lwpns.has_space())
11465 {
11466 Lwpns.del(0);
11467 }
11468
11469 if(!Lwpns.has_space(2))
11470 {
11471 Lwpns.del(0);
11472 }
11473
11474 switch(dir)
11475 {
11476 case up:
11477 {
11478 hookshot_used=true;
11479 hs_switcher = sw;
11480 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wHSHandle,hookitem,
11481 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11482 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11483 Lwpns.add(new weapon((zfix)wx,(zfix)wy-4,(zfix)wz,wHookshot,hookitem,
11484 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11485 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11486 hs_startx=wx;
11487 hs_starty=wy-4;
11488 }
11489 break;
11490
11491 case down:
11492 {
11493 int32_t offset=get_bit(quest_rules,qr_HOOKSHOTDOWNBUG)?4:0;
11494 hookshot_used=true;
11495 hs_switcher = sw;
11496 Lwpns.add(new weapon((zfix)wx,(zfix)wy+offset,(zfix)wz,wHSHandle,hookitem,
11497 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11498 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11499 Lwpns.add(new weapon((zfix)wx,(zfix)wy+offset,(zfix)wz,wHookshot,hookitem,
11500 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11501 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11502 hs_startx=wx;
11503 hs_starty=wy;
11504 }
11505 break;
11506
11507 case left:
11508 {
11509 hookshot_used=true;
11510 hs_switcher = sw;
11511 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wHSHandle,hookitem,
11512 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11513 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11514 Lwpns.add(new weapon((zfix)(wx-4),(zfix)wy,(zfix)wz,wHookshot,hookitem,
11515 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11516 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11517 hs_startx=wx-4;
11518 hs_starty=wy;
11519 }
11520 break;
11521
11522 case right:
11523 {
11524 hookshot_used=true;
11525 hs_switcher = sw;
11526 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wHSHandle,hookitem,
11527 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11528 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11529 Lwpns.add(new weapon((zfix)(wx+4),(zfix)wy,(zfix)wz,wHookshot,hookitem,
11530 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11531 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11532 hs_startx=wx+4;
11533 hs_starty=wy;
11534 }
11535 break;
11536 //Diagonal Hookshot (7)
11537 case r_down:
11538 {
11539 hookshot_used=true;
11540 hs_switcher = sw;
11541 int32_t offset=get_bit(quest_rules,qr_HOOKSHOTDOWNBUG)?4:0;
11542 Lwpns.add(new weapon((zfix)wx,(zfix)wy+offset,(zfix)wz,wHSHandle,hookitem,
11543 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11544 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11545 Lwpns.add(new weapon((zfix)(wx+4),(zfix)wy+offset,(zfix)wz,wHookshot,hookitem,
11546 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11547 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11548 hs_startx=wx+4;
11549 hs_starty=wy;
11550 }
11551 break;
11552
11553 case r_up:
11554 {
11555 hookshot_used=true;
11556 hs_switcher = sw;
11557 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wHSHandle,hookitem,
11558 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11559 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11560 Lwpns.add(new weapon((zfix)(wx+4),(zfix)wy,(zfix)wz,wHookshot,hookitem,
11561 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11562 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11563 hs_startx=wx+4;
11564 hs_starty=wy;
11565 }
11566 break;
11567
11568 case l_down:
11569 {
11570 hookshot_used=true;
11571 hs_switcher = sw;
11572 int32_t offset=get_bit(quest_rules,qr_HOOKSHOTDOWNBUG)?4:0;
11573 Lwpns.add(new weapon((zfix)wx,(zfix)wy+offset,(zfix)wz,wHSHandle,hookitem,
11574 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11575 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11576 Lwpns.add(new weapon((zfix)(wx-4),(zfix)wy+offset,(zfix)wz,wHookshot,hookitem,
11577 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11578 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11579 hs_startx=wx+4;
11580 hs_starty=wy;
11581 }
11582 break;
11583
11584 case l_up:
11585 {
11586 hookshot_used=true;
11587 hs_switcher = sw;
11588 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wHSHandle,hookitem,
11589 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11590 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11591 Lwpns.add(new weapon((zfix)(wx-4),(zfix)wy,(zfix)wz,wHookshot,hookitem,
11592 hookpower*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11593 ((weapon*)Lwpns.spr(Lwpns.Count()-1))->family_class = itm.family;
11594 hs_startx=wx+4;
11595 hs_starty=wy;
11596 }
11597 break;
11598 }
11599 hookshot_frozen=true;
11600 }
11601 if(insta_switch)
11602 {
11603 weapon* w = (weapon*)Lwpns.spr(Lwpns.idFirst(wHookshot));
11604 hooked_combopos = cpos;
11605 w->misc=2;
11606 w->step=0;
11607 doSwitchHook(itm.misc5);
11608 if(itm.usesound2)
11609 sfx(itm.usesound2,pan(int32_t(x)));
11610 else if(QMisc.miscsfx[sfxSWITCHED])
11611 sfx(QMisc.miscsfx[sfxSWITCHED],int32_t(x));
11612 stop_sfx(itm.usesound);
11613 }
11614 }
11615 break;
11616
11617 case itype_dinsfire:
11618 if(z!=0 || fakez!=0 || (isSideViewHero() && !(on_sideview_solid_oldpos(x,y,old_x,old_y) || getOnSideviewLadder() || IsSideSwim())))
11619 return false;
11620
11621 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11622 {
11623 if(QMisc.miscsfx[sfxERROR])
11624 sfx(QMisc.miscsfx[sfxERROR]);
11625 return false;
11626 }
11627
11628 paymagiccost(itemid);
11629 if (IsSideSwim()) {action=sideswimcasting; FFCore.setHeroAction(sideswimcasting);}
11630 else {action=casting; FFCore.setHeroAction(casting);}
11631 magicitem=itemid;
11632 break;
11633
11634 case itype_faroreswind:
11635 if(z!=0 || fakez!=0 || (isSideViewHero() && !(on_sideview_solid_oldpos(x,y,old_x,old_y) || getOnSideviewLadder() || IsSideSwim())))
11636 return false;
11637
11638 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11639 {
11640 if(QMisc.miscsfx[sfxERROR])
11641 sfx(QMisc.miscsfx[sfxERROR]);
11642 return false;
11643 }
11644
11645 paymagiccost(itemid);
11646 if (IsSideSwim()) {action=sideswimcasting; FFCore.setHeroAction(sideswimcasting);}
11647 else {action=casting; FFCore.setHeroAction(casting);}
11648 magicitem=itemid;
11649 break;
11650
11651 case itype_nayruslove:
11652 if(z!=0 || fakez!=0 || (isSideViewHero() && !(on_sideview_solid_oldpos(x,y,old_x,old_y) || getOnSideviewLadder() || IsSideSwim())))
11653 return false;
11654
11655 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11656 {
11657 if(QMisc.miscsfx[sfxERROR])
11658 sfx(QMisc.miscsfx[sfxERROR]);
11659 return false;
11660 }
11661
11662 paymagiccost(itemid);
11663 if (IsSideSwim()) {action=sideswimcasting; FFCore.setHeroAction(sideswimcasting);}
11664 else {action=casting; FFCore.setHeroAction(casting);}
11665 magicitem=itemid;
11666 break;
11667
11668 case itype_cbyrna:
11669 {
11670 //Beams already deployed
11671 if(Lwpns.idCount(wCByrna))
11672 {
11673 stopCaneOfByrna();
11674 return false;
11675 }
11676
11677 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11678 {
11679 stop_sfx(itm.usesound); //if we can't pay the cost, kill the sound.
11680 //last_cane_of_byrna_item_id = -1; //no, we'd do this in a byrna cleanup function.
11681 return false;
11682 }
11683
11684 paymagiccost(itemid);
11685 last_cane_of_byrna_item_id = itemid;
11686 //zprint("itm.misc3: %d\n", itm.misc3);
11687 for(int32_t i=0; i<itm.misc3; i++)
11688 {
11689 //byrna weapons are added here
11690 //space them apart
11691 //zprint("Added byrna weapon %d.\n", i);
11692 //the iterator isn passed to 'type'. weapons.cpp converts thisd to
11693 //'quantity_iterator' pn construction; and this is used for orbit initial spacing.
11694 Lwpns.add(new weapon((zfix)wx,(zfix)wy,(zfix)wz,wCByrna,i,itm.power*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11695 //Lwpns.add(new weapon((zfix)wx+cos(2 * PI / (i+1)),(zfix)wy+sin(2 * PI / (i+1)),(zfix)wz,wCByrna,i,itm.power*game->get_hero_dmgmult(),dir,itemid,getUID(),false,false,true));
11696 //wx += cos(2 * PI / (itm.misc3-i));
11697 //wy += sin(2 * PI / (itm.misc3-i));
11698 }
11699 if(!(Lwpns.idCount(wCByrna)))
11700 stop_sfx(itm.usesound); //If we can't create the beams, kill the sound.
11701 }
11702 break;
11703
11704 case itype_clock:
11705 {
11706 ret = false;
11707 if(!(itm.flags & ITEM_FLAG1))
11708 break; //Passive clock, don't use
11709 if((itm.flags & ITEM_FLAG2) && watch) //"Can't activate while clock active"
11710 break;
11711 if(!(checkbunny(itemid) && checkmagiccost(itemid))) //cost/bunny check
11712 {
11713 if(QMisc.miscsfx[sfxERROR])
11714 sfx(QMisc.miscsfx[sfxERROR]);
11715 return false;
11716 }
11717
11718 paymagiccost(itemid);
11719
11720 setClock(watch=true);
11721
11722 for(int32_t i=0; i<eMAXGUYS; i++)
11723 clock_zoras[i]=0;
11724
11725 clockclk=itm.misc1;
11726 sfx(itm.usesound);
11727 break;
11728 }
11729 case itype_killem:
11730 {
11731 ret = false;
11732 if(!(itm.flags & ITEM_FLAG1))
11733 break; //Passive killemall, don't use
11734
11735 if(!(checkbunny(itemid) && checkmagiccost(itemid))
11736 || !can_kill_em_all()) //No enemies onscreen
11737 {
11738 if(QMisc.miscsfx[sfxERROR])
11739 sfx(QMisc.miscsfx[sfxERROR]);
11740 return false;
11741 }
11742
11743 paymagiccost(itemid);
11744
11745 kill_em_all();
11746 sfx(itm.usesound);
11747 break;
11748 }
11749 case itype_refill:
11750 {
11751 if(!(checkbunny(itemid) && checkmagiccost(itemid)))
11752 {
11753 if(QMisc.miscsfx[sfxERROR])
11754 sfx(QMisc.miscsfx[sfxERROR]);
11755 return false;
11756 }
11757
11758 bool did_something = false;
11759
11760 if(itm.flags & ITEM_FLAG1) //Cure sword jinx
11761 {
11762 if(swordclk)
11763 did_something = true;
11764 swordclk = 0;
11765 verifyAWpn();
11766 }
11767 for(auto q = 0; q < 5; ++q)
11768 {
11769 auto ctr = itm.misc(q);
11770 if(unsigned(ctr) >= MAX_COUNTERS)
11771 continue;
11772 int16_t amnt = vbound(itm.misc(q+5),-32768,32767);
11773 if(!amnt) continue;
11774 bool gradual = itm.flags & ITEM_FLAG2;
11775 if(amnt > 0)
11776 {
11777 if(game->get_counter(ctr) + game->get_dcounter(ctr) >= game->get_maxcounter(ctr))
11778 {
11779 //Can't *do* anything... skip
11780 continue;
11781 }
11782 if(game->get_counter(ctr) >= game->get_maxcounter(ctr))
11783 {
11784 //Can't do anything unless affecting dcounter
11785 gradual = true;
11786 }
11787 }
11788 else //Negative
11789 {
11790 if(game->get_counter(ctr) + game->get_dcounter(ctr) <= 0)
11791 {
11792 //Can't *do* anything... skip
11793 continue;
11794 }
11795 if(game->get_counter(ctr) <= 0)
11796 {
11797 //Can't do anything unless affecting dcounter
11798 gradual = true;
11799 }
11800 }
11801 did_something = true;
11802 if(gradual) //Gradual
11803 {
11804 game->change_dcounter(amnt, ctr);
11805 }
11806 else
11807 {
11808 game->change_counter(amnt, ctr);
11809 }
11810 }
11811 if(!did_something)
11812 {
11813 if(QMisc.miscsfx[sfxERROR])
11814 sfx(QMisc.miscsfx[sfxERROR]);
11815 return false;
11816 }
11817 paymagiccost(itemid);
11818 sfx(itm.usesound);
11819 ret = false;
11820 break;
11821 }
11822
11823 default:
11824 ret = false;
11825 }
11826
11827
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if(itm.flags & ITEM_DOWNGRADE)
11828 {
11829 game->set_item(itemid,false);
11830
11831 // Maybe Item Override has allowed the same item in both slots?
11832 if(Bwpn == itemid)
11833 {
11834 Bwpn = 0;
11835 game->forced_bwpn = -1;
11836 verifyBWpn();
11837 }
11838
11839 if(Awpn == itemid)
11840 {
11841 Awpn = 0;
11842 game->forced_awpn = -1;
11843 verifyAWpn();
11844 }
11845
11846 if(Xwpn == itemid)
11847 {
11848 Xwpn = 0;
11849 game->forced_xwpn = -1;
11850 verifyXWpn();
11851 }
11852
11853 if(Ywpn == itemid)
11854 {
11855 Ywpn = 0;
11856 game->forced_ywpn = -1;
11857 verifyYWpn();
11858 }
11859 }
11860
11861 12 return ret;
11862 17 }
11863
11864
11865 255 bool HeroClass::doattack()
11866 {
11867 //int32_t s = BSZ ? 0 : 11;
11868 255 int32_t s = (zinit.heroAnimationStyle==las_bszelda) ? 0 : 11;
11869
11870
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 255 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
255 int32_t bugnetid = (directWpn>-1 && itemsbuf[directWpn].family==itype_bugnet) ? directWpn : current_item_id(itype_bugnet);
11871
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 255 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
255 if(attack==wBugNet && bugnetid!=-1)
11872 {
11873 if(++attackclk >= NET_CLK_TOTAL)
11874 return false;
11875
11876 return true;
11877 }
11878
11879 // Abort attack if attackclk has run out and:
11880 // * the attack is not Hammer, Sword with Spin Scroll, Candle, or Wand, OR
11881 // * you aren't holding down the A button, you're not charging, and/or you're still spinning
11882
11883
3/6
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 238 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
255 if(attackclk>=(spins>0?8:14) && attack!=wHammer &&
11884
4/12
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
17 (((attack!=wSword || !current_item(itype_spinscroll) || inlikelike) && attack!=wWand && attack!=wFire && attack!=wCByrna) || !((attack==wSword && isWpnPressed(itype_sword) && spins==0) || charging>0)))
11885 {
11886 17 tapping=false;
11887 17 return false;
11888 }
11889
11890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
238 if(attackclk>29)
11891 {
11892 tapping=false;
11893 return false;
11894 }
11895
11896
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
238 int32_t candleid = (directWpn>-1 && itemsbuf[directWpn].family==itype_candle) ? directWpn : current_item_id(itype_candle);
11897
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
238 int32_t byrnaid = (directWpn>-1 && itemsbuf[directWpn].family==itype_cbyrna) ? directWpn : current_item_id(itype_cbyrna);
11898 // An attack can be "walked out-of" after 8 frames, unless it's:
11899 // * a sword stab
11900 // * a hammer pound
11901 // * a wand thrust
11902 // * a candle thrust
11903 // * a cane thrust
11904 // In which case it should continue.
11905
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 238 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 238 times.
238 if((attack==wCatching && attackclk>4)||(attack!=wWand && attack!=wSword && attack!=wHammer
11906 && (attack!=wFire || (candleid!=-1 && !(itemsbuf[candleid].wpn)))
11907 && (attack!=wCByrna || (byrnaid!=-1 && !(itemsbuf[byrnaid].wpn)))
11908 && (attack != wBugNet) && attackclk>7))
11909 {
11910 if(DrunkUp()||DrunkDown()||DrunkLeft()||DrunkRight())
11911 {
11912 lstep = s;
11913 return false;
11914 }
11915 }
11916
11917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
238 if(charging==0)
11918 {
11919 238 lstep=0;
11920 238 }
11921
11922 // Work out the sword charge-up delay
11923 238 int32_t magiccharge = 192, normalcharge = 64;
11924 238 int32_t itemid = current_item_id(itype_chargering);
11925
11926
1/2
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
238 if(itemid>=0)
11927 {
11928 normalcharge = itemsbuf[itemid].misc1;
11929 magiccharge = itemsbuf[itemid].misc2;
11930 }
11931
11932 238 itemid = current_item_id(attack==wHammer ? itype_quakescroll : itype_spinscroll);
11933
11934 238 bool doCharge=true;
11935
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
238 if(z!=0 && fakez != 0)
11936 doCharge=false;
11937
1/2
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
238 if(attack==wSword)
11938 {
11939
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
238 if(!(attackclk==SWORDCHARGEFRAME && isWpnPressed(itype_sword)))
11940 238 doCharge=false;
11941 else if(charging<=normalcharge)
11942 {
11943 if(itemid<0 || !(checkbunny(itemid) && checkmagiccost(itemid)))
11944 doCharge=false;
11945 }
11946 238 }
11947 else if(attack==wHammer)
11948 {
11949 if(!(attackclk==HAMMERCHARGEFRAME && isWpnPressed(itype_hammer)))
11950 doCharge=false;
11951 else if(charging<=normalcharge)
11952 {
11953 if(itemid<0 || !(checkbunny(itemid) && checkmagiccost(itemid)))
11954 doCharge=false;
11955 }
11956 }
11957 else
11958 doCharge=false;
11959
11960 // Now work out the magic cost
11961 238 itemid = current_item_id(attack==wHammer ? itype_quakescroll : itype_spinscroll);
11962
11963 // charging up weapon...
11964 //
11965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
238 if(doCharge)
11966 {
11967 // Increase charging while holding down button.
11968 if(spins==0 && charging<magiccharge)
11969 charging++;
11970
11971 // Once a charging threshold is reached, play the sound.
11972 if(charging==normalcharge)
11973 {
11974 paymagiccost(itemid); //!DIMITODO: Can this underflow or even just do it even if you don't have magic?
11975 sfx(WAV_ZN1CHARGE,pan(x.getInt()));
11976 }
11977 else if(charging==magiccharge)
11978 {
11979 itemid = current_item_id(attack==wHammer ? itype_quakescroll2 : itype_spinscroll2);
11980
11981 if(itemid>-1 && checkbunny(itemid) && checkmagiccost(itemid))
11982 {
11983 paymagiccost(itemid);
11984 charging++; // charging>magiccharge signifies a successful supercharge.
11985 sfx(WAV_ZN1CHARGE2,pan(x.getInt()));
11986 }
11987 }
11988 }
11989
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
238 else if(attack==wCByrna && byrnaid!=-1)
11990 {
11991 if(!(itemsbuf[byrnaid].wpn))
11992 {
11993 attack = wNone;
11994 return startwpn(attackid); // Beam if the Byrna stab animation WASN'T used.
11995 }
11996
11997 bool beamcount = false;
11998
11999 for(int32_t i=0; i<Lwpns.Count(); i++)
12000 {
12001 weapon *w = ((weapon*)Lwpns.spr(i));
12002
12003 if(w->id==wCByrna)
12004 {
12005 beamcount = true;
12006 break;
12007 }
12008 }
12009
12010 // If beams already deployed, remove them
12011 if(!attackclk && beamcount)
12012 {
12013 return startwpn(attackid); // Remove beams instantly
12014 }
12015
12016 // Otherwise, continue
12017 ++attackclk;
12018 }
12019 else
12020 {
12021 238 ++attackclk;
12022
12023
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
238 if(attackclk==SWORDCHARGEFRAME && charging>0 && !tapping) //Signifies a tapped enemy
12024 {
12025 ++attackclk; // Won't continue charging
12026 charging=0;
12027 }
12028
12029 // Faster if spinning.
12030
1/2
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
238 if(spins>0)
12031 ++attackclk;
12032
12033 // Even faster if hurricane spinning.
12034
1/2
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
238 if(spins>5)
12035 attackclk+=2;
12036
12037 // If at a charging threshold, do a charged attack.
12038
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
238 if(charging>=normalcharge && (attack!=wSword || attackclk>=SWORDCHARGEFRAME) && !tapping)
12039 {
12040 if(attack==wSword)
12041 {
12042 spins=(charging>magiccharge ? (itemsbuf[current_item_id(itype_spinscroll2)].misc1*4)-3
12043 : (itemsbuf[current_item_id(itype_spinscroll)].misc1*4)+1);
12044 attackclk=1;
12045 sfx(itemsbuf[current_item_id(spins>5 ? itype_spinscroll2 : itype_spinscroll)].usesound,pan(x.getInt()));
12046 }
12047 /*
12048 else if(attack==wWand)
12049 {
12050 //Not reachable.. yet
12051 spins=1;
12052 }
12053 */
12054 else if(attack==wHammer && sideviewhammerpound())
12055 {
12056 spins=1; //signifies the quake hammer
12057 bool super = (charging>magiccharge && current_item(itype_quakescroll2));
12058 sfx(itemsbuf[current_item_id(super ? itype_quakescroll2 : itype_quakescroll)].usesound,pan(x.getInt()));
12059 quakeclk=(itemsbuf[current_item_id(super ? itype_quakescroll2 : itype_quakescroll)].misc1);
12060
12061 // general area stun
12062 for(int32_t i=0; i<GuyCount(); i++)
12063 {
12064 if(!isflier(GuyID(i)))
12065 {
12066 StunGuy(i,(itemsbuf[current_item_id(super ? itype_quakescroll2 : itype_quakescroll)].misc2)-
12067 distance(x,y,GuyX(i),GuyY(i)));
12068 }
12069 }
12070 }
12071 }
12072
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
238 else if(tapping && attackclk<SWORDCHARGEFRAME && charging<magiccharge)
12073 charging++;
12074
12075
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 238 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 238 times.
✓ Branch 6 taken 124 times.
✓ Branch 7 taken 114 times.
238 if(!isWpnPressed(attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : itype_sword))
12076 114 charging=0;
12077
12078
1/2
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
238 if(attackclk>=SWORDCHARGEFRAME)
12079 tapping = false;
12080 }
12081
12082
3/8
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 221 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
238 if(attackclk==1 && attack==wFire && candleid!=-1 && !(itemsbuf[candleid].wpn))
12083 {
12084 return startwpn(attackid); // Flame if the Candle stab animation WASN'T used.
12085 }
12086
12087 238 int32_t crossid = current_item_id(itype_crossscroll); //has Cross Beams scroll
12088
12089
5/12
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 204 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
238 if(attackclk==13 || (attackclk==7 && spins>1 && crossid >=0 && checkbunny(crossid) && checkmagiccost(crossid)))
12090 {
12091
12092
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
17 int32_t wpnid = (directWpn>-1 && itemsbuf[directWpn].family==itype_sword) ? directWpn : current_item_id(itype_sword);
12093
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 int64_t templife = wpnid>=0? itemsbuf[wpnid].misc1 : 0;
12094
12095
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
17 if(wpnid>=0 && itemsbuf[wpnid].flags & ITEM_FLAG1)
12096 {
12097 17 templife=templife*game->get_maxlife();
12098 17 templife=templife/100;
12099 17 }
12100 else
12101 {
12102 templife*=game->get_hp_per_heart();
12103 }
12104
12105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 bool normalbeam = (int64_t(game->get_life())+(get_bit(quest_rules,qr_QUARTERHEART)?((game->get_hp_per_heart()/4)-1):((game->get_hp_per_heart()/2)-1))>=templife);
12106 17 int32_t perilid = current_item_id(itype_perilscroll);
12107
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
17 bool perilbeam = (perilid>=0 && wpnid>=0 && game->get_life()<=itemsbuf[perilid].misc1*game->get_hp_per_heart()
12108 && checkbunny(perilid) && checkmagiccost(perilid)
12109 // Must actually be able to shoot sword beams
12110 && ((itemsbuf[wpnid].flags & ITEM_FLAG1)
12111 || itemsbuf[wpnid].misc1 <= game->get_maxlife()/game->get_hp_per_heart()));
12112
12113
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
17 if(attack==wSword && !tapping)
12114 {
12115
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
17 if(perilbeam || normalbeam)
12116 {
12117
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if(attackclk==7)
12118 paymagiccost(crossid); // Pay the Cross Beams magic cost.
12119
12120
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
17 if(perilbeam && !normalbeam)
12121 paymagiccost(perilid); // Pay the Peril Beam magic cost.
12122
12123 // TODO: Something that would be cheap but disgraceful to hack in at this point is
12124 // a way to make the peril/cross beam item's power stat influence the strength
12125 // of the peril/cross beam...
12126 17 startwpn(attackid);
12127 17 }
12128 else misc_internal_hero_flags &= ~LF_PAID_SWORD_COST;
12129 17 }
12130
12131
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if(attack==wWand)
12132 startwpn(attackid); // Flame if the Wand stab animation WAS used (it always is).
12133
12134
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
17 if(attack==wFire && candleid!=-1 && itemsbuf[candleid].wpn) // Flame if the Candle stab animation WAS used.
12135 startwpn(attackid);
12136
12137
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
17 if(attack==wCByrna && byrnaid!=-1 && itemsbuf[byrnaid].wpn) // Beam if the Byrna stab animation WAS used.
12138 startwpn(attackid);
12139 17 }
12140
12141
2/2
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 17 times.
238 if(attackclk==14)
12142 17 lstep = s;
12143
12144 238 return true;
12145 255 }
12146
12147 3046 bool HeroClass::can_attack()
12148 {
12149
2/4
✓ Branch 0 taken 3046 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3046 times.
✗ Branch 3 not taken.
3046 int32_t currentSwordOrWand = (itemsbuf[dowpn].family == itype_wand || itemsbuf[dowpn].family == itype_sword)?dowpn:-1;
12150
3/6
✓ Branch 0 taken 3046 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3046 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3046 times.
✗ Branch 5 not taken.
3046 if(action==hopping || action==swimming || action==freeze || action==sideswimfreeze
12151
4/8
✓ Branch 0 taken 3046 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3046 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3046 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3046 times.
✗ Branch 7 not taken.
3046 || lstunclock > 0 || is_conveyor_stunned || spins>0 || usingActiveShield()
12152
3/4
✓ Branch 0 taken 3046 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2553 times.
✓ Branch 3 taken 493 times.
3046 || ((action==attacking||action==sideswimattacking)
12153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3046 times.
3046 && ((attack!=wSword && attack!=wWand) || !(itemsbuf[currentSwordOrWand].flags & ITEM_FLAG5))
12154
1/2
✓ Branch 0 taken 3046 times.
✗ Branch 1 not taken.
3046 && charging!=0))
12155 {
12156 return false;
12157 }
12158
12159 3046 int32_t r = (isdungeon()) ? 16 : 0;
12160 3046 int32_t r2 = get_bit(quest_rules, qr_NOBORDER) ? 0 : 8;
12161
12162
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 3046 times.
✓ Branch 2 taken 1072 times.
✓ Branch 3 taken 1974 times.
✗ Branch 4 not taken.
3046 if(!get_bit(quest_rules, qr_ITEMSONEDGES)) switch(dir)
12163 {
12164 case up:
12165 case down:
12166
2/2
✓ Branch 0 taken 1060 times.
✓ Branch 1 taken 12 times.
1072 return !(y<(r2+r) || y>(160-r-r2));
12167
12168 case left:
12169 case right:
12170
2/2
✓ Branch 0 taken 1950 times.
✓ Branch 1 taken 24 times.
1974 return !(x<(r2+r) || x>(240-r-r2));
12171 }
12172
12173 return true;
12174 3046 }
12175
12176 bool isRaftFlag(int32_t flag)
12177 {
12178 return (flag==mfRAFT || flag==mfRAFT_BRANCH || flag==mfRAFT_BOUNCE);
12179 }
12180
12181 1523 void handle_lens_triggers(int32_t l_id)
12182 {
12183
1/2
✓ Branch 0 taken 1523 times.
✗ Branch 1 not taken.
1523 bool enabled = l_id >= 0 && (itemsbuf[l_id].flags & ITEM_FLAG6);
12184
2/2
✓ Branch 0 taken 1523 times.
✓ Branch 1 taken 10661 times.
12184 for(auto layer = 0; layer < 7; ++layer)
12185 {
12186 10661 mapscr* tmp = FFCore.tempScreens[layer];
12187
2/2
✓ Branch 0 taken 1876336 times.
✓ Branch 1 taken 10661 times.
1886997 for(auto pos = 0; pos < 176; ++pos)
12188 {
12189 1876336 newcombo const& cmb = combobuf[tmp->data[pos]];
12190
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1876336 times.
✓ Branch 2 taken 1876336 times.
✗ Branch 3 not taken.
1876336 if(enabled ? (cmb.triggerflags[1] & combotriggerLENSON)
12191 1876336 : (cmb.triggerflags[1] & combotriggerLENSOFF))
12192 {
12193 do_trigger_combo(layer, pos);
12194 }
12195 1876336 }
12196 10661 }
12197 1523 }
12198
12199 1523 void do_lens()
12200 {
12201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1523 times.
1523 if ( FFCore.getQuestHeaderInfo(vZelda) < 0x250 ) //2.10 or earlier
12202 {
12203 do_210_lens();
12204 return;
12205 }
12206
12207 1523 int32_t wpnPressed = getWpnPressed(itype_lens);
12208
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1523 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1523 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1523 times.
1523 int32_t itemid = lensid >= 0 ? lensid : wpnPressed>0 ? wpnPressed : Hero.getLastLensID()>0 ? Hero.getLastLensID() : current_item_id(itype_lens);
12209
1/2
✓ Branch 0 taken 1523 times.
✗ Branch 1 not taken.
1523 if(itemid >= 0)
12210 {
12211 if(isWpnPressed(itype_lens) && checkitem_jinx(itemid) && !lensclk && checkbunny(itemid) && checkmagiccost(itemid))
12212 {
12213 if(lensid<0)
12214 {
12215 lensid=itemid;
12216 if(itemsbuf[itemid].family == itype_lens)
12217 Hero.setLastLensID(itemid);
12218 if(get_bit(quest_rules,qr_MORESOUNDS)) sfx(itemsbuf[itemid].usesound);
12219 }
12220
12221 paymagiccost(itemid, true); //Needs to ignore timer cause lensclk is our timer.
12222
12223 if(itemid>=0 && itemsbuf[itemid].script != 0 && !did_scriptl && !(item_doscript[itemid] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)))
12224 {
12225 //clear the item script stack for a new script
12226 //itemScriptData[(itemid & 0xFFF)].Clear();
12227 //for ( int32_t q = 0; q < 1024; q++ ) item_stack[(itemid & 0xFFF)][q] = 0;
12228 ri = &(itemScriptData[itemid]);
12229 for ( int32_t q = 0; q < 1024; q++ ) item_stack[itemid][q] = 0xFFFF;
12230 ri->Clear();
12231 //ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[itemid].script, itemid & 0xFFF);
12232 item_doscript[itemid] = 1;
12233 itemscriptInitialised[itemid] = 0;
12234 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[itemid].script, itemid);
12235 did_scriptl=true;
12236 }
12237
12238 if (itemsbuf[itemid].magiccosttimer[0]) lensclk = itemsbuf[itemid].magiccosttimer[0];
12239 else lensclk = 12;
12240 }
12241 else
12242 {
12243 did_scriptl=false;
12244 if(!lensclk)
12245 {
12246
12247 if(lensid>-1)
12248 {
12249 lensid=-1;
12250 lensclk = 0;
12251
12252 if(get_bit(quest_rules,qr_MORESOUNDS)) sfx(WAV_ZN1LENSOFF);
12253 }
12254 }
12255 }
12256 }
12257 1523 handle_lens_triggers(lensid);
12258 1523 }
12259 //Add 2.10 version check to call this
12260 void do_210_lens()
12261 {
12262 int32_t itemid = lensid >= 0 ? lensid : directWpn>-1 ? directWpn : current_item_id(itype_lens);
12263
12264 if(itemid<0)
12265 return;
12266
12267 if(isWpnPressed(itype_lens) && checkitem_jinx(itemid) && !lensclk && checkmagiccost(itemid))
12268 {
12269 if(lensid<0)
12270 {
12271 lensid=itemid;
12272
12273 if(get_bit(quest_rules,qr_MORESOUNDS)) sfx(itemsbuf[itemid].usesound);
12274 }
12275
12276 paymagiccost(itemid, true);
12277
12278 if(itemid>=0 && itemsbuf[itemid].script != 0 && !did_scriptl && !(item_doscript[itemid] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)))
12279 {
12280 //clear the item script stack for a new script
12281 //itemScriptData[(itemid & 0xFFF)].Clear();
12282 ri = &(itemScriptData[itemid]);
12283 for ( int32_t q = 0; q < 1024; q++ ) item_stack[itemid][q] = 0xFFFF;
12284 ri->Clear();
12285 //for ( int32_t q = 0; q < 1024; q++ ) item_stack[(itemid & 0xFFF)][q] = 0;
12286 //ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[itemid].script, itemid & 0xFFF);
12287 item_doscript[itemid] = 1;
12288 itemscriptInitialised[itemid] = 0;
12289 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[itemid].script, itemid);
12290 did_scriptl=true;
12291 }
12292
12293 if (itemsbuf[itemid].magiccosttimer[0]) lensclk = itemsbuf[itemid].magiccosttimer[0];
12294 else lensclk = 12;
12295 }
12296 else
12297 {
12298 did_scriptl=false;
12299
12300 if(lensid>-1 && !(isWpnPressed(itype_lens) && checkitem_jinx(itemid) && checkmagiccost(itemid)))
12301 {
12302 lensid=-1;
12303 lensclk = 0;
12304
12305 if(get_bit(quest_rules,qr_MORESOUNDS)) sfx(WAV_ZN1LENSOFF);
12306 }
12307 }
12308 }
12309
12310 void HeroClass::do_hopping()
12311 {
12312 do_lens();
12313
12314 if(hopclk==0xFF) //|| (diagonalMovement && hopclk >= 0xFF) )) // swimming
12315 //Possible fix for exiting water in diagonal movement. -Z
12316 {
12317 int32_t flippers_id = current_item_id(itype_flippers);
12318 if(diveclk>0)
12319 {
12320 --diveclk;
12321 if(flippers_id > -1 && itemsbuf[flippers_id].flags & ITEM_FLAG2 && DrunkrAbtn()) //Cancellable Diving -V
12322 {
12323 diveclk = itemsbuf[flippers_id].misc2;
12324 }
12325 }
12326 else if(DrunkrAbtn())
12327 {
12328 bool global_diving=(flippers_id > -1 && itemsbuf[flippers_id].flags & ITEM_FLAG1);
12329 bool screen_diving=(tmpscr->flags5&fTOGGLEDIVING) != 0;
12330
12331 if(global_diving==screen_diving)
12332 diveclk = (flippers_id < 0 ? 80 : (itemsbuf[flippers_id].misc1 + itemsbuf[flippers_id].misc2));
12333 }
12334
12335 if((!(x.getInt()&7) && !(y.getInt()&7)) || (diagonalMovement||NO_GRIDLOCK))
12336 {
12337 SetSwim();
12338 hopclk = 0;
12339 if (!IsSideSwim())
12340 {
12341 charging = attackclk = 0;
12342 tapping = false;
12343 }
12344 }
12345 else
12346 {
12347 herostep();
12348
12349 if(!isDiving() || (frame&1))
12350 {
12351 switch(dir)
12352 {
12353 case up:
12354 y -= 1;
12355 break;
12356
12357 case down:
12358 y += 1;
12359 break;
12360
12361 case left:
12362 x -= 1;
12363 break;
12364
12365 case right:
12366 x += 1;
12367 break;
12368 }
12369 }
12370 }
12371 }
12372 else // hopping in or out (need to separate the cases...)
12373 {
12374 if((diagonalMovement||NO_GRIDLOCK))
12375 {
12376 if(hopclk==1) //hopping out
12377 //>= 1 possible fix for getting stuck on land edges.
12378 //No, this is not a clock. it's a type. 1 == out, 2 == in.
12379 {
12380 if(hopdir!=-1) dir=hopdir;
12381
12382 landswim=0;
12383
12384 if(dir==up)
12385 {
12386 herostep();
12387 herostep();
12388 int32_t sidestep=0;
12389
12390 if(iswaterex(MAPCOMBO(x,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x,y+(bigHitbox?0:8)-1, true, false) && !iswaterex(MAPCOMBO(x+8,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x+8,y+(bigHitbox?0:8)-1, true, false) && !iswaterex(MAPCOMBO(x+15,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x+15,y+(bigHitbox?0:8)-1, true, false))
12391 sidestep=1;
12392 else if(!iswaterex(MAPCOMBO(x,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x,y+(bigHitbox?0:8)-1, true, false) && !iswaterex(MAPCOMBO(x+7,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x+7,y+(bigHitbox?0:8)-1, true, false) && iswaterex(MAPCOMBO(x+15,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x+15,y+(bigHitbox?0:8)-1, true, false))
12393 sidestep=2;
12394
12395 if(sidestep==1) x++;
12396 else if(sidestep==2) x--;
12397 else y--;
12398
12399 if(!iswaterex(MAPCOMBO(x.getInt(),y.getInt()+(bigHitbox?0:8)), currmap, currscr, -1, x.getInt(),y.getInt()+(bigHitbox?0:8), true, false)&&!iswaterex(MAPCOMBO(x.getInt(),y.getInt()+15), currmap, currscr, -1, x.getInt(),y.getInt()+15, true, false))
12400 {
12401 hopclk=0;
12402 diveclk=0;
12403 action=none; FFCore.setHeroAction(none);
12404 hopdir=-1;
12405 }
12406 }
12407
12408 if(dir==down)
12409 {
12410 herostep();
12411 herostep();
12412 int32_t sidestep=0;
12413
12414 if(iswaterex(MAPCOMBO(x,y+16), currmap, currscr, -1, x,y+16, true, false) && !iswaterex(MAPCOMBO(x+8,y+16), currmap, currscr, -1, x+8,y+16, true, false) && !iswaterex(MAPCOMBO(x+15,y+16), currmap, currscr, -1, x+15,y+16, true, false))
12415 sidestep=1;
12416 else if(!iswaterex(MAPCOMBO(x,y+16), currmap, currscr, -1, x,y+16, true, false) && !iswaterex(MAPCOMBO(x+8,y+16), currmap, currscr, -1, x+8,y+16, true, false) && iswaterex(MAPCOMBO(x+15,y+16), currmap, currscr, -1, x+15,y+16, true, false))
12417 sidestep=2;
12418
12419 if(sidestep==1) x++;
12420 else if(sidestep==2) x--;
12421 else y++;
12422
12423 if(!iswaterex(MAPCOMBO(x.getInt(),y.getInt()+(bigHitbox?0:8)), currmap, currscr, -1, x.getInt(),y.getInt()+(bigHitbox?0:8), true, false)&&!iswaterex(MAPCOMBO(x.getInt(),y.getInt()+15), currmap, currscr, -1, x.getInt(),y.getInt()+15, true, false))
12424 {
12425 hopclk=0;
12426 diveclk=0;
12427 action=none; FFCore.setHeroAction(none);
12428 hopdir=-1;
12429 }
12430 }
12431
12432 if(dir==left)
12433 {
12434 herostep();
12435 herostep();
12436 int32_t sidestep=0;
12437
12438 if(iswaterex(MAPCOMBO(x-1,y+(bigHitbox?0:8)), currmap, currscr, -1, x-1,y+(bigHitbox?0:8), true, false) && !iswaterex(MAPCOMBO(x-1,y+(bigHitbox?8:12)), currmap, currscr, -1, x-1,y+(bigHitbox?8:12), true, false) && !iswaterex(MAPCOMBO(x-1,y+15), currmap, currscr, -1, x-1,y+15, true, false))
12439 sidestep=1;
12440 else if(!iswaterex(MAPCOMBO(x-1,y+(bigHitbox?0:8)), currmap, currscr, -1, x-1,y+(bigHitbox?0:8), true, false) && !iswaterex(MAPCOMBO(x-1,y+(bigHitbox?7:11)), currmap, currscr, -1, x-1,y+(bigHitbox?7:11), true, false) && iswaterex(MAPCOMBO(x-1,y+15), currmap, currscr, -1, x-1,y+15, true, false))
12441 sidestep=2;
12442
12443 if(sidestep==1) y++;
12444 else if(sidestep==2) y--;
12445 else x--;
12446
12447 if(!iswaterex(MAPCOMBO(x.getInt(),y.getInt()+(bigHitbox?0:8)), currmap, currscr, -1, x.getInt(),y.getInt()+(bigHitbox?0:8), true, false)&&!iswaterex(MAPCOMBO(x.getInt()+15,y.getInt()+8), currmap, currscr, -1, x.getInt()+15,y.getInt()+8, true, false))
12448 {
12449 hopclk=0;
12450 diveclk=0;
12451 action=none; FFCore.setHeroAction(none);
12452 hopdir=-1;
12453 }
12454 }
12455
12456 if(dir==right)
12457 {
12458 herostep();
12459 herostep();
12460 int32_t sidestep=0;
12461
12462 if(iswaterex(MAPCOMBO(x+16,y+(bigHitbox?0:8)), currmap, currscr, -1, x+16,y+(bigHitbox?0:8), true, false) && !iswaterex(MAPCOMBO(x+16,y+(bigHitbox?8:12)), currmap, currscr, -1, x+16,y+(bigHitbox?8:12), true, false) && !iswaterex(MAPCOMBO(x+16,y+15), currmap, currscr, -1, x+16,y+15, true, false))
12463 sidestep=1;
12464 else if(!iswaterex(MAPCOMBO(x+16,y+(bigHitbox?0:8)), currmap, currscr, -1, x+16,y+(bigHitbox?0:8), true, false) && !iswaterex(MAPCOMBO(x+16,y+(bigHitbox?7:11)), currmap, currscr, -1, x+16,y+(bigHitbox?7:11), true, false) && iswaterex(MAPCOMBO(x+16,y+15), currmap, currscr, -1, x+16,y+15, true, false))
12465 sidestep=2;
12466
12467 if(sidestep==1) y++;
12468 else if(sidestep==2) y--;
12469 else x++;
12470
12471 if(!iswaterex(MAPCOMBO(x.getInt(),y.getInt()+(bigHitbox?0:8)), currmap, currscr, -1, x.getInt(),y.getInt()+(bigHitbox?0:8), true, false)&&!iswaterex(MAPCOMBO(x.getInt()+15,y.getInt()+8), currmap, currscr, -1, x.getInt()+15,y.getInt()+8, true, false))
12472 {
12473 hopclk=0;
12474 diveclk=0;
12475 action=none; FFCore.setHeroAction(none);
12476 hopdir=-1;
12477 }
12478 }
12479 }
12480
12481 if(hopclk==2) //hopping in
12482 {
12483 landswim=0;
12484
12485 if(dir==up)
12486 {
12487 herostep();
12488 herostep();
12489 int32_t sidestep=0;
12490
12491 if(!iswaterex(MAPCOMBO(x,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x,y+(bigHitbox?0:8)-1, true, false) && iswaterex(MAPCOMBO(x+8,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x+8,y+(bigHitbox?0:8)-1, true, false) && iswaterex(MAPCOMBO(x+15,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x+15,y+(bigHitbox?0:8)-1, true, false))
12492 sidestep=1;
12493 else if(iswaterex(MAPCOMBO(x,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x,y+(bigHitbox?0:8)-1, true, false) && iswaterex(MAPCOMBO(x+7,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x+7,y+(bigHitbox?0:8)-1, true, false) && !iswaterex(MAPCOMBO(x+15,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x+15,y+(bigHitbox?0:8)-1, true, false))
12494 sidestep=2;
12495
12496 if(sidestep==1) x++;
12497 else if(sidestep==2) x--;
12498 else y--;
12499
12500 if(iswaterex(MAPCOMBO(x.getInt(),y.getInt()+(bigHitbox?0:8)), currmap, currscr, -1, x.getInt(),y.getInt()+(bigHitbox?0:8), true, false)&&iswaterex(MAPCOMBO(x.getInt(),y.getInt()+15), currmap, currscr, -1, x.getInt(),y.getInt()+15, true, false))
12501 {
12502 hopclk=0xFF;
12503 diveclk=0;
12504 SetSwim();
12505 }
12506 }
12507
12508 if(dir==down)
12509 {
12510 herostep();
12511 herostep();
12512 int32_t sidestep=0;
12513
12514 if(!iswaterex(MAPCOMBO(x,y+16), currmap, currscr, -1, x,y+16, true, false) && iswaterex(MAPCOMBO(x+8,y+16), currmap, currscr, -1, x+8,y+16, true, false) && iswaterex(MAPCOMBO(x+15,y+16), currmap, currscr, -1, x+15,y+16, true, false))
12515 sidestep=1;
12516 else if(iswaterex(MAPCOMBO(x,y+16), currmap, currscr, -1, x,y+16, true, false) && iswaterex(MAPCOMBO(x+8,y+16), currmap, currscr, -1, x+8,y+16, true, false) && !iswaterex(MAPCOMBO(x+15,y+16), currmap, currscr, -1, x+15,y+16, true, false))
12517 sidestep=2;
12518
12519 if(sidestep==1) x++;
12520 else if(sidestep==2) x--;
12521 else y++;
12522
12523 if(iswaterex(MAPCOMBO(x.getInt(),y.getInt()+(bigHitbox?0:8)), currmap, currscr, -1, x.getInt(),y.getInt()+(bigHitbox?0:8), true, false)&&iswaterex(MAPCOMBO(x.getInt(),y.getInt()+15), currmap, currscr, -1, x.getInt(),y.getInt()+15, true, false))
12524 {
12525 hopclk=0xFF;
12526 diveclk=0;
12527 SetSwim();
12528 if (!IsSideSwim()) reset_swordcharge();
12529 }
12530 }
12531
12532 if(dir==left)
12533 {
12534 herostep();
12535 herostep();
12536 int32_t sidestep=0;
12537
12538 if(!iswaterex(MAPCOMBO(x-1,y+(bigHitbox?0:8)), currmap, currscr, -1, x-1,y+(bigHitbox?0:8), true, false) && iswaterex(MAPCOMBO(x-1,y+(bigHitbox?8:12)), currmap, currscr, -1, x-1,y+(bigHitbox?8:12), true, false) && iswaterex(MAPCOMBO(x-1,y+15), currmap, currscr, -1, x-1,y+15, true, false))
12539 sidestep=1;
12540 else if(iswaterex(MAPCOMBO(x-1,y+(bigHitbox?0:8)), currmap, currscr, -1, x-1,y+(bigHitbox?0:8), true, false) && iswaterex(MAPCOMBO(x-1,y+(bigHitbox?7:11)), currmap, currscr, -1, x-1,y+(bigHitbox?7:11), true, false) && !iswaterex(MAPCOMBO(x-1,y+15), currmap, currscr, -1, x-1,y+15, true, false))
12541 sidestep=2;
12542
12543 if(sidestep==1) y++;
12544 else if(sidestep==2) y--;
12545 else x--;
12546
12547 if(iswaterex(MAPCOMBO(x.getInt(),y.getInt()+(bigHitbox?0:8)), currmap, currscr, -1, x.getInt(),y.getInt()+(bigHitbox?0:8), true, false)&&iswaterex(MAPCOMBO(x.getInt()+15,y.getInt()+8), currmap, currscr, -1, x.getInt()+15,y.getInt()+8, true, false))
12548 {
12549 hopclk=0xFF;
12550 diveclk=0;
12551 SetSwim();
12552 }
12553 }
12554
12555 if(dir==right)
12556 {
12557 herostep();
12558 herostep();
12559
12560 int32_t sidestep=0;
12561
12562 if(!iswaterex(MAPCOMBO(x+16,y+(bigHitbox?0:8)), currmap, currscr, -1, x+16,y+(bigHitbox?0:8), true, false) && iswaterex(MAPCOMBO(x+16,y+(bigHitbox?8:12)), currmap, currscr, -1, x+16,y+(bigHitbox?8:12), true, false) && iswaterex(MAPCOMBO(x+16,y+15), currmap, currscr, -1, x+16,y+15, true, false))
12563 sidestep=1;
12564 else if(iswaterex(MAPCOMBO(x+16,y+(bigHitbox?0:8)), currmap, currscr, -1, x+16,y+(bigHitbox?0:8), true, false) && iswaterex(MAPCOMBO(x+16,y+(bigHitbox?7:11)), currmap, currscr, -1, x+16,y+(bigHitbox?7:11), true, false) && !iswaterex(MAPCOMBO(x+16,y+15), currmap, currscr, -1, x+16,y+15, true, false))
12565 sidestep=2;
12566
12567 if(sidestep==1) y++;
12568 else if(sidestep==2) y--;
12569 else x++;
12570
12571 if(iswaterex(MAPCOMBO(x.getInt(),y.getInt()+(bigHitbox?0:8)), currmap, currscr, -1, x.getInt(),y.getInt()+(bigHitbox?0:8), true, false)&&iswaterex(MAPCOMBO(x.getInt()+15,y.getInt()+8), currmap, currscr, -1, x.getInt()+15,y.getInt()+8, true, false))
12572 {
12573 hopclk=0xFF;
12574 diveclk=0;
12575 SetSwim();
12576 }
12577 }
12578 }
12579
12580 }
12581 else
12582 {
12583 if((dir<left ? !(x.getInt()&7) && !(y.getInt()&15) : !(x.getInt()&15) && !(y.getInt()&7)))
12584 {
12585 action=none; FFCore.setHeroAction(none);
12586 hopclk = 0;
12587 diveclk = 0;
12588
12589 if(iswaterex(MAPCOMBO(x.getInt(),y.getInt()+8), currmap, currscr, -1, x.getInt(),y.getInt()+8, true, false))
12590 {
12591 // hopped in
12592 SetSwim();
12593 if (!IsSideSwim()) attackclk = charging = spins = 0;
12594 }
12595 }
12596 else
12597 {
12598 herostep();
12599 herostep();
12600
12601 if(++hero_count>(16*hero_animation_speed))
12602 hero_count=0;
12603
12604 int32_t xofs2 = x.getInt()&15;
12605 int32_t yofs2 = y.getInt()&15;
12606 int32_t s = 1 + (frame&1);
12607
12608 switch(dir)
12609 {
12610 case up:
12611 if(yofs2<3 || yofs2>13) --y;
12612 else y-=s;
12613
12614 break;
12615
12616 case down:
12617 if(yofs2<3 || yofs2>13) ++y;
12618 else y+=s;
12619
12620 break;
12621
12622 case left:
12623 if(xofs2<3 || xofs2>13) --x;
12624 else x-=s;
12625
12626 break;
12627
12628 case right:
12629 if(xofs2<3 || xofs2>13) ++x;
12630 else x+=s;
12631
12632 break;
12633 }
12634 }
12635 }
12636 }
12637 }
12638
12639 void HeroClass::do_rafting()
12640 {
12641
12642 if(toogam)
12643 {
12644 action=none; FFCore.setHeroAction(none);
12645 return;
12646 }
12647
12648 FFCore.setHeroAction(rafting);
12649
12650 do_lens();
12651
12652 herostep();
12653
12654 //Calculate rafting speed
12655 int32_t raft_item = current_item_id(itype_raft);
12656 int32_t raft_step = (raft_item < 0 ? 1 : itemsbuf[raft_item].misc1);
12657 raft_step = vbound(raft_step, -8, 5);
12658 int32_t raft_time = raft_step < 0 ? 1<<(-raft_step) : 1;
12659 if(raft_step < 0) raft_step = 1;
12660 int32_t step_inc = 1 << (raft_step - 1);
12661 // Fix position
12662 if(raft_step > 1)
12663 {
12664 if(x.getInt() & (step_inc-1))
12665 {
12666 x = x.getInt() & ~(step_inc-1);
12667 }
12668 if(y.getInt() & (step_inc-1))
12669 {
12670 y = y.getInt() & ~(step_inc-1);
12671 }
12672 }
12673 // Inc clock, check if we need to move this frame
12674 ++raftclk;
12675 if((raftclk % raft_time) || raft_step == 0) return; //No movement this frame
12676
12677 if(!(x.getInt()&15) && !(y.getInt()&15))
12678 {
12679 // this sections handles switching to raft branches
12680 if((MAPFLAG(x,y)==mfRAFT_BRANCH||MAPCOMBOFLAG(x,y)==mfRAFT_BRANCH))
12681 {
12682 if(dir!=down && DrunkUp() && (isRaftFlag(nextflag(x,y,up,false))||isRaftFlag(nextflag(x,y,up,true))))
12683 {
12684 dir = up;
12685 goto skip;
12686 }
12687
12688 if(dir!=up && DrunkDown() && (isRaftFlag(nextflag(x,y,down,false))||isRaftFlag(nextflag(x,y,down,true))))
12689 {
12690 dir = down;
12691 goto skip;
12692 }
12693
12694 if(dir!=right && DrunkLeft() && (isRaftFlag(nextflag(x,y,left,false))||isRaftFlag(nextflag(x,y,left,true))))
12695 {
12696 dir = left;
12697 goto skip;
12698 }
12699
12700 if(dir!=left && DrunkRight() && (isRaftFlag(nextflag(x,y,right,false))||isRaftFlag(nextflag(x,y,right,true))))
12701 {
12702 dir = right;
12703 goto skip;
12704 }
12705 }
12706 else if((MAPFLAG(x,y)==mfRAFT_BOUNCE||MAPCOMBOFLAG(x,y)==mfRAFT_BOUNCE))
12707 {
12708 if(dir == left) dir = right;
12709 else if(dir == right) dir = left;
12710 else if(dir == up) dir = down;
12711 else if(dir == down) dir = up;
12712 }
12713
12714
12715 if(!isRaftFlag(nextflag(x,y,dir,false))&&!isRaftFlag(nextflag(x,y,dir,true)))
12716 {
12717 if(dir<left) //going up or down
12718 {
12719 if((isRaftFlag(nextflag(x,y,right,false))||isRaftFlag(nextflag(x,y,right,true))))
12720 dir=right;
12721 else if((isRaftFlag(nextflag(x,y,left,false))||isRaftFlag(nextflag(x,y,left,true))))
12722 dir=left;
12723 else if(y>0 && y<160)
12724 {
12725 action=none; FFCore.setHeroAction(none);
12726 x = x.getInt();
12727 y = y.getInt();
12728 }
12729 }
12730 else //going left or right
12731 {
12732 if((isRaftFlag(nextflag(x,y,down,false))||isRaftFlag(nextflag(x,y,down,true))))
12733 dir=down;
12734 else if((isRaftFlag(nextflag(x,y,up,false))||isRaftFlag(nextflag(x,y,up,true))))
12735 dir=up;
12736 else if(x>0 && x<240)
12737 {
12738 action=none; FFCore.setHeroAction(none);
12739 x = x.getInt();
12740 y = y.getInt();
12741 }
12742 }
12743 }
12744 }
12745
12746 skip:
12747
12748 switch(dir)
12749 {
12750 case up:
12751 if(x.getInt()&15)
12752 {
12753 if(x.getInt()&8)
12754 x++;
12755 else x--;
12756 }
12757 else y -= step_inc;
12758
12759 break;
12760
12761 case down:
12762 if(x.getInt()&15)
12763 {
12764 if(x.getInt()&8)
12765 x++;
12766 else x--;
12767 }
12768 else y += step_inc;
12769
12770 break;
12771
12772 case left:
12773 if(y.getInt()&15)
12774 {
12775 if (get_bit(quest_rules, qr_BETTER_RAFT_2))
12776 {
12777 if ((y.getInt() % 16) < 4) y--;
12778 else y++;
12779 }
12780 else
12781 {
12782 if(y.getInt()&8)
12783 y++;
12784 else y--;
12785 }
12786 }
12787 else x -= step_inc;
12788
12789 break;
12790
12791 case right:
12792 if(y.getInt()&15)
12793 {
12794 if (get_bit(quest_rules, qr_BETTER_RAFT_2))
12795 {
12796 if ((y.getInt() % 16) <= 4) y--;
12797 else y++;
12798 }
12799 else
12800 {
12801 if(y.getInt()&8)
12802 y++;
12803 else y--;
12804 }
12805 }
12806 else x += step_inc;
12807
12808 break;
12809 }
12810 }
12811
12812 bool HeroClass::try_hover()
12813 {
12814 if(hoverclk <= 0 && can_use_item(itype_hoverboots,i_hoverboots) && !ladderx && !laddery && !(hoverflags & HOV_OUT))
12815 {
12816 int32_t itemid = current_item_id(itype_hoverboots);
12817 if(hoverclk < 0)
12818 hoverclk = -hoverclk;
12819 else
12820 {
12821 fall = fakefall = jumping = 0;
12822 if(itemsbuf[itemid].misc1)
12823 hoverclk = itemsbuf[itemid].misc1;
12824 else
12825 {
12826 hoverclk = 1;
12827 hoverflags |= HOV_INF;
12828 }
12829
12830
12831 sfx(itemsbuf[itemid].usesound,pan(x.getInt()));
12832 }
12833 if(itemsbuf[itemid].wpn)
12834 decorations.add(new dHover(x, y, dHOVER, 0));
12835 return true;
12836 }
12837 return false;
12838 }
12839
12840 //Returns bitwise; lower 8 are dir pulled in, next 16 are combo ID, 25th bit is bool for if can be resisted
12841 //Returns '-1' if not being pulled
12842 //Returns '-2' if should be falling in
12843 6949 int32_t HeroClass::check_pitslide(bool ignore_hover)
12844 {
12845 //Pitfall todo -Emily
12846 //Iron boots; can't fight slipping, 2px/frame
12847 //Scripted variables to read pull dir/clk (clk only for non-hero)
12848 //Implement falling for all sprite types (npc AI)
12849 // Fall/slipping tiles for enemies
12850 // Fall/slipping SFX for enemies
12851 // Fall SFX for items/weapons
12852 // Weapons/Misc sprite shared for falling items/weapons
12853 //Maybe slip SFX for Hero?
12854 // Weapons/Misc sprite override for falling sprite?
12855 //Update std.zh with relevant new stuff
12856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6949 times.
6949 if(can_pitfall(ignore_hover))
12857 {
12858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6949 times.
6949 bool can_diag = (diagonalMovement || get_bit(quest_rules,qr_DISABLE_4WAY_GRIDLOCK));
12859 6949 int32_t ispitul = getpitfall(x,y+(bigHitbox?0:8));
12860 6949 int32_t ispitbl = getpitfall(x,y+15);
12861 6949 int32_t ispitur = getpitfall(x+15,y+(bigHitbox?0:8));
12862 6949 int32_t ispitbr = getpitfall(x+15,y+15);
12863 6949 int32_t ispitul_50 = getpitfall(x+8,y+(bigHitbox?8:12));
12864 6949 int32_t ispitbl_50 = getpitfall(x+8,y+(bigHitbox?7:11));
12865 6949 int32_t ispitur_50 = getpitfall(x+7,y+(bigHitbox?8:12));
12866 6949 int32_t ispitbr_50 = getpitfall(x+7,y+(bigHitbox?7:11));
12867 6949 int32_t ispitul_75 = getpitfall(x+12,y+(bigHitbox?12:14));
12868 6949 int32_t ispitbl_75 = getpitfall(x+12,y+(bigHitbox?3:9));
12869 6949 int32_t ispitur_75 = getpitfall(x+3,y+(bigHitbox?12:14));
12870 6949 int32_t ispitbr_75 = getpitfall(x+3,y+(bigHitbox?3:9));
12871 static const int32_t flag_pit_irresistable = (1<<24);
12872
1/5
✓ Branch 0 taken 6949 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6949 switch((ispitul?1:0) + (ispitur?1:0) + (ispitbl?1:0) + (ispitbr?1:0))
12873 {
12874 case 4: return -2; //Fully over pit; fall in
12875 case 3:
12876 {
12877 if(ispitul && ispitur && ispitbl) //UL_3
12878 {
12879 if(ispitul_50)
12880 {
12881 if(!ispitul_75 && (DrunkDown() || DrunkRight())) return -1;
12882 return (can_diag ? l_up : left) | (ispitul_75 ? flag_pit_irresistable : 0) | (ispitul << 8);
12883 }
12884 }
12885 else if(ispitul && ispitur && ispitbr) //UR_3
12886 {
12887 if(ispitur_50)
12888 {
12889 if(!ispitur_75 && (DrunkDown() || DrunkLeft())) return -1;
12890 return (can_diag ? r_up : right) | (ispitur_75 ? flag_pit_irresistable : 0) | (ispitur << 8);
12891 }
12892 }
12893 else if(ispitul && ispitbl && ispitbr) //BL_3
12894 {
12895 if(ispitbl_50)
12896 {
12897 if(!ispitbl_75 && (DrunkUp() || DrunkRight())) return -1;
12898 return (can_diag ? l_down : left) | (ispitbl_75 ? flag_pit_irresistable : 0) | (ispitbl << 8);
12899 }
12900 }
12901 else if(ispitbl && ispitur && ispitbr) //BR_3
12902 {
12903 if(ispitbr_50)
12904 {
12905 if(!ispitbr_75 && (DrunkUp() || DrunkLeft())) return -1;
12906 return (can_diag ? r_down : right) | (ispitbr_75 ? flag_pit_irresistable : 0) | (ispitbr << 8);
12907 }
12908 }
12909 break;
12910 }
12911 case 2:
12912 {
12913 if(ispitul && ispitur) //Up
12914 {
12915 if(DrunkDown())
12916 {
12917 if(ispitul_75 && ispitur_75) //Straight up
12918 {
12919 return up | flag_pit_irresistable | (ispitul << 8);
12920 }
12921 else if(ispitul_75)
12922 {
12923 return (can_diag ? l_up : left) | flag_pit_irresistable | (ispitul << 8);
12924 }
12925 else if(ispitur_75)
12926 {
12927 return (can_diag ? r_up : right) | flag_pit_irresistable | (ispitur << 8);
12928 }
12929 else return -1;
12930 }
12931 else
12932 {
12933 if(ispitul_50 && ispitur_50) //Straight up
12934 {
12935 return up | ((ispitul_75 || ispitur_75) ? flag_pit_irresistable : 0) | (ispitul << 8);
12936 }
12937 else if(ispitul_50)
12938 {
12939 if(DrunkRight() && !ispitul_75) return -1;
12940 return (can_diag ? l_up : left) | (ispitul_75 ? flag_pit_irresistable : 0) | (ispitul << 8);
12941 }
12942 else if(ispitur_50)
12943 {
12944 if(DrunkLeft() && !ispitur_75) return -1;
12945 return (can_diag ? r_up : right) | (ispitur_75 ? flag_pit_irresistable : 0) | (ispitur << 8);
12946 }
12947 }
12948 }
12949 else if(ispitbl && ispitbr) //Down
12950 {
12951 if(DrunkUp())
12952 {
12953 if(ispitbl_75 && ispitbr_75) //Straight down
12954 {
12955 return down | flag_pit_irresistable | (ispitbl << 8);
12956 }
12957 else if(ispitbl_75)
12958 {
12959 return (can_diag ? l_down : left) | flag_pit_irresistable | (ispitbl << 8);
12960 }
12961 else if(ispitbr_75)
12962 {
12963 return (can_diag ? r_down : right) | flag_pit_irresistable | (ispitbr << 8);
12964 }
12965 else return -1;
12966 }
12967 else
12968 {
12969 if(ispitbl_50 && ispitbr_50) //Straight down
12970 {
12971 return down | ((ispitbl_75 || ispitbr_75) ? flag_pit_irresistable : 0) | (ispitbl << 8);
12972 }
12973 else if(ispitbl_50)
12974 {
12975 if(DrunkRight() && !ispitbl_75) return -1;
12976 return (can_diag ? l_down : left) | (ispitbl_75 ? flag_pit_irresistable : 0) | (ispitbl << 8);
12977 }
12978 else if(ispitbr_50)
12979 {
12980 if(DrunkLeft() && !ispitbr_75) return -1;
12981 return (can_diag ? r_down : right) | (ispitbr_75 ? flag_pit_irresistable : 0) | (ispitbr << 8);
12982 }
12983 }
12984 }
12985 else if(ispitbl && ispitul) //Left
12986 {
12987 if(DrunkRight())
12988 {
12989 if(ispitul_75 && ispitbl_75) //Straight left
12990 {
12991 return left | flag_pit_irresistable | (ispitul << 8);
12992 }
12993 else if(ispitul_75)
12994 {
12995 return (can_diag ? l_up : up) | flag_pit_irresistable | (ispitul << 8);
12996 }
12997 else if(ispitbl_75)
12998 {
12999 return (can_diag ? l_down : down) | flag_pit_irresistable | (ispitbl << 8);
13000 }
13001 else return -1;
13002 }
13003 else
13004 {
13005 if(ispitul_50 && ispitbl_50) //Straight left
13006 {
13007 return left | ((ispitul_75 || ispitbl_75) ? flag_pit_irresistable : 0) | (ispitul << 8);
13008 }
13009 else if(ispitul_50)
13010 {
13011 if(DrunkDown() && !ispitul_75) return -1;
13012 return (can_diag ? l_up : up) | (ispitul_75 ? flag_pit_irresistable : 0) | (ispitul << 8);
13013 }
13014 else if(ispitbl_50)
13015 {
13016 if(DrunkUp() && !ispitbl_75) return -1;
13017 return (can_diag ? l_down : down) | (ispitbl_75 ? flag_pit_irresistable : 0) | (ispitbl << 8);
13018 }
13019 }
13020 }
13021 else if(ispitbr && ispitur) //Right
13022 {
13023 if(DrunkLeft())
13024 {
13025 if(ispitur_75 && ispitbr_75) //Straight right
13026 {
13027 return right | flag_pit_irresistable | (ispitur << 8);
13028 }
13029 else if(ispitur_75)
13030 {
13031 return (can_diag ? r_up : up) | flag_pit_irresistable | (ispitur << 8);
13032 }
13033 else if(ispitbr_75)
13034 {
13035 return (can_diag ? r_down : down) | flag_pit_irresistable | (ispitbr << 8);
13036 }
13037 else return -1;
13038 }
13039 else
13040 {
13041 if(ispitur_50 && ispitbr_50) //Straight right
13042 {
13043 return right | ((ispitur_75 || ispitbr_75) ? flag_pit_irresistable : 0) | (ispitur << 8);
13044 }
13045 else if(ispitur_50)
13046 {
13047 if(DrunkDown() && !ispitur_75) return -1;
13048 return (can_diag ? r_up : up) | (ispitur_75 ? flag_pit_irresistable : 0) | (ispitur << 8);
13049 }
13050 else if(ispitbr_50)
13051 {
13052 if(DrunkUp() && !ispitbr_75) return -1;
13053 return (can_diag ? r_down : down) | (ispitbr_75 ? flag_pit_irresistable : 0) | (ispitbr << 8);
13054 }
13055 }
13056 }
13057 break;
13058 }
13059 case 1:
13060 {
13061 if(ispitul && ispitul_50) //UL_1
13062 {
13063 if(!ispitul_75 && (DrunkDown() || DrunkRight())) return -1;
13064 return (can_diag ? l_up : left) | (ispitul_75 ? flag_pit_irresistable : 0) | (ispitul << 8);
13065 }
13066 if(ispitur && ispitur_50) //UR_1
13067 {
13068 if(!ispitur_75 && (DrunkDown() || DrunkLeft())) return -1;
13069 return (can_diag ? r_up : right) | (ispitur_75 ? flag_pit_irresistable : 0) | (ispitur << 8);
13070 }
13071 if(ispitbl && ispitbl_50) //BL_1
13072 {
13073 if(!ispitbl_75 && (DrunkUp() || DrunkRight())) return -1;
13074 return (can_diag ? l_down : left) | (ispitbl_75 ? flag_pit_irresistable : 0) | (ispitbl << 8);
13075 }
13076 if(ispitbr && ispitbr_50) //BR_1
13077 {
13078 if(!ispitbr_75 && (DrunkUp() || DrunkLeft())) return -1;
13079 return (can_diag ? r_down : right) | (ispitbr_75 ? flag_pit_irresistable : 0) | (ispitbr << 8);
13080 }
13081 break;
13082 }
13083 }
13084 6949 }
13085 6949 return -1;
13086 6949 }
13087
13088 1285 bool HeroClass::pitslide() //Runs pitslide movement; returns true if pit is irresistable
13089 {
13090 1285 pitfall();
13091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1285 times.
1285 if(fallclk) return true;
13092 1285 int32_t val = check_pitslide();
13093 //Val should not be -2 here; if -2 would have been returned, the 'return true' above should have triggered!
13094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1285 times.
1285 if(val == -1)
13095 {
13096 1285 pit_pulldir = -1;
13097 1285 pit_pullclk = 0;
13098 1285 return false;
13099 }
13100 int32_t dir = val&0xFF;
13101 int32_t cmbid = (val&0xFFFF00)>>8;
13102 int32_t sensitivity = combobuf[cmbid].attribytes[2];
13103 if(combobuf[cmbid].usrflags&cflag5) //No pull at all
13104 {
13105 pit_pulldir = -1;
13106 pit_pullclk = 0;
13107 return false;
13108 }
13109 if(dir > -1 && !(hoverflags & HOV_PITFALL_OUT) && try_hover()) //Engage hovers
13110 {
13111 pit_pulldir = -1;
13112 pit_pullclk = 0;
13113 return false;
13114 }
13115 pit_pulldir = dir;
13116 int32_t step = 1;
13117 if(sensitivity == 0)
13118 {
13119 step = 2;
13120 sensitivity = 1;
13121 }
13122 if(pit_pullclk++ % sensitivity) //No pull this frame
13123 return (val&0x100);
13124 for(; step > 0 && !fallclk; --step)
13125 {
13126 switch(dir)
13127 {
13128 case l_up: case l_down: case left:
13129 --x; break;
13130 case r_up: case r_down: case right:
13131 ++x; break;
13132 }
13133 switch(dir)
13134 {
13135 case l_up: case r_up: case up:
13136 --y; break;
13137 case l_down: case r_down: case down:
13138 ++y; break;
13139 }
13140 pitfall();
13141 }
13142 return fallclk || (val&0x100);
13143 1285 }
13144
13145 1285 void HeroClass::pitfall()
13146 {
13147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1285 times.
1285 if(fallclk)
13148 {
13149 drop_liftwpn();
13150 if(fallclk == PITFALL_FALL_FRAMES && fallCombo) sfx(combobuf[fallCombo].attribytes[0], pan(x.getInt()));
13151 //Handle falling
13152 if(!--fallclk)
13153 {
13154 int32_t dmg = game->get_hp_per_heart()/4;
13155 bool dmg_perc = false;
13156 bool warp = false;
13157
13158 action=none; FFCore.setHeroAction(none);
13159 newcombo* cmb = fallCombo ? &combobuf[fallCombo] : NULL;
13160 if(cmb)
13161 {
13162 dmg = cmb->attributes[0]/10000L;
13163 dmg_perc = cmb->usrflags&cflag3;
13164 warp = cmb->usrflags&cflag1;
13165 }
13166 if(dmg) //Damage
13167 {
13168 if(dmg > 0) hclk=48; //IFrames only if damaged, not if healed
13169 game->set_life(vbound(int32_t(dmg_perc ? game->get_life() - ((vbound(dmg,-100,100)/100.0)*game->get_maxlife()) : (game->get_life()-int64_t(dmg))),0,game->get_maxlife()));
13170 }
13171 if(warp) //Warp
13172 {
13173 sdir = dir;
13174 if(cmb->usrflags&cflag2) //Direct Warp
13175 {
13176 didpit=true;
13177 pitx=x;
13178 pity=y;
13179 }
13180 dowarp(0,vbound(cmb->attribytes[1],0,3),0);
13181 }
13182 else //Reset to screen entry
13183 {
13184 go_respawn_point();
13185 }
13186 }
13187 }
13188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1285 times.
1285 else if(can_pitfall())
13189 {
13190 1285 bool ispitul = ispitfall(x,y+(bigHitbox?0:8));
13191 1285 bool ispitbl = ispitfall(x,y+15);
13192 1285 bool ispitur = ispitfall(x+15,y+(bigHitbox?0:8));
13193 1285 bool ispitbr = ispitfall(x+15,y+15);
13194 1285 int32_t pitctr = getpitfall(x+8,y+(bigHitbox?8:12));
13195
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1285 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1285 if(ispitul && ispitbl && ispitur && ispitbr && pitctr)
13196 {
13197 if(!(hoverflags & HOV_PITFALL_OUT) && try_hover()) return;
13198 if(!bigHitbox && !ispitfall(x,y)) y = (y.getInt() + 8 - (y.getInt() % 8)); //Make the falling sprite fully over the pit
13199 fallclk = PITFALL_FALL_FRAMES;
13200 fallCombo = pitctr;
13201 action=falling; FFCore.setHeroAction(falling);
13202 spins = 0;
13203 charging = 0;
13204 drop_liftwpn();
13205 }
13206 1285 }
13207 1285 }
13208
13209 1523 void HeroClass::movehero()
13210 {
13211
2/4
✓ Branch 0 taken 1523 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1523 times.
1523 if(lstunclock || is_conveyor_stunned) return;
13212 1523 int32_t xoff=x.getInt()&7;
13213 1523 int32_t yoff=y.getInt()&7;
13214
1/2
✓ Branch 0 taken 1523 times.
✗ Branch 1 not taken.
1523 if(NO_GRIDLOCK)
13215 {
13216 xoff = 0;
13217 yoff = 0;
13218 }
13219 1523 int32_t push=pushing;
13220 1523 int32_t oldladderx=-1000, oldladdery=-1000; // moved here because linux complains "init crosses goto ~Koopa
13221 1523 pushing=0;
13222 1523 zfix temp_step(hero_newstep);
13223 1523 zfix temp_x(x);
13224 1523 zfix temp_y(y);
13225
13226 1523 int32_t flippers_id = current_item_id(itype_flippers);
13227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1523 times.
1523 if(diveclk>0)
13228 {
13229 if (isSideViewHero() && get_bit(quest_rules,qr_SIDESWIM)) diveclk = 0;
13230 --diveclk;
13231 if(isDiving() && flippers_id > -1 && itemsbuf[flippers_id].flags & ITEM_FLAG2 && DrunkrAbtn()) //Cancellable Diving -V
13232 {
13233 diveclk = itemsbuf[flippers_id].misc2;
13234 }
13235 }
13236
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1523 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1523 else if(action == swimming && DrunkrAbtn())
13237 {
13238 bool global_diving=(flippers_id > -1 && itemsbuf[flippers_id].flags & ITEM_FLAG1);
13239 bool screen_diving=(tmpscr->flags5&fTOGGLEDIVING) != 0;
13240
13241 if(global_diving==screen_diving)
13242 diveclk = (flippers_id < 0 ? 80 : (itemsbuf[flippers_id].misc1 + itemsbuf[flippers_id].misc2));
13243 }
13244
13245
1/2
✓ Branch 0 taken 1523 times.
✗ Branch 1 not taken.
1523 if(action==rafting)
13246 {
13247 do_rafting();
13248
13249 if(action==rafting)
13250 {
13251 return;
13252 }
13253
13254
13255 set_respawn_point();
13256 trySideviewLadder();
13257 }
13258
13259 1523 int32_t olddirectwpn = directWpn; // To be reinstated if startwpn() fails
13260 1523 int32_t btnwpn = -1;
13261
13262 //&0xFFF removes the "bow & arrows" bitmask
13263 //The Quick Sword is allowed to interrupt attacks.
13264
2/4
✓ Branch 0 taken 1523 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1523 times.
✗ Branch 3 not taken.
1523 int32_t currentSwordOrWand = (itemsbuf[dowpn].family == itype_wand || itemsbuf[dowpn].family == itype_sword)?dowpn:-1;
13265
5/8
✓ Branch 0 taken 1285 times.
✓ Branch 1 taken 238 times.
✓ Branch 2 taken 1285 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 238 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 238 times.
1523 if((!attackclk && action!=attacking && action != sideswimattacking) || ((attack==wSword || attack==wWand) && (itemsbuf[currentSwordOrWand].flags & ITEM_FLAG5)))
13266 {
13267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1285 times.
1285 if(DrunkrBbtn())
13268 {
13269 btnwpn=getItemFamily(itemsbuf,Bwpn&0xFFF);
13270 dowpn = Bwpn&0xFFF;
13271 directWpn = directItemB;
13272 }
13273
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1268 times.
1285 else if(DrunkrAbtn())
13274 {
13275 17 btnwpn=getItemFamily(itemsbuf,Awpn&0xFFF);
13276 17 dowpn = Awpn&0xFFF;
13277 17 directWpn = directItemA;
13278 17 }
13279
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1268 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1268 else if(get_bit(quest_rules,qr_SET_XBUTTON_ITEMS) && DrunkrEx1btn())
13280 {
13281 btnwpn=getItemFamily(itemsbuf,Xwpn&0xFFF);
13282 dowpn = Xwpn&0xFFF;
13283 directWpn = directItemX;
13284 }
13285
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1268 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1268 else if(get_bit(quest_rules,qr_SET_YBUTTON_ITEMS) && DrunkrEx2btn())
13286 {
13287 btnwpn=getItemFamily(itemsbuf,Ywpn&0xFFF);
13288 dowpn = Ywpn&0xFFF;
13289 directWpn = directItemY;
13290 }
13291
13292
1/2
✓ Branch 0 taken 1285 times.
✗ Branch 1 not taken.
1285 if(directWpn > 255) directWpn = 0;
13293
13294 // The Quick Sword only allows repeated sword or wand swings.
13295
3/8
✓ Branch 0 taken 1285 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1285 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1285 times.
1285 if((action==attacking||action==sideswimattacking) && ((attack==wSword && btnwpn!=itype_sword) || (attack==wWand && btnwpn!=itype_wand)))
13296 btnwpn=-1;
13297 1285 }
13298
13299
1/2
✓ Branch 0 taken 1523 times.
✗ Branch 1 not taken.
1523 auto swordid = (directWpn>-1 ? directWpn : current_item_id(itype_sword));
13300
9/12
✓ Branch 0 taken 1481 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 1336 times.
✓ Branch 3 taken 145 times.
✓ Branch 4 taken 1336 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1336 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 17 times.
✓ Branch 9 taken 1319 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 17 times.
1523 if(can_attack() && (swordid > -1 && itemsbuf[swordid].family==itype_sword) && checkitem_jinx(swordid) && btnwpn==itype_sword && charging==0)
13301 {
13302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 attackid=directWpn>-1 ? directWpn : current_item_id(itype_sword);
13303
2/6
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
17 if(checkbunny(attackid) && (checkmagiccost(attackid) || !(itemsbuf[attackid].flags & ITEM_FLAG6)))
13304 {
13305
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
17 if((itemsbuf[attackid].flags & ITEM_FLAG6) && !(misc_internal_hero_flags & LF_PAID_SWORD_COST))
13306 {
13307 paymagiccost(attackid,true);
13308 misc_internal_hero_flags |= LF_PAID_SWORD_COST;
13309 }
13310 17 SetAttack();
13311 17 attack=wSword;
13312
13313 17 attackclk=0;
13314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 sfx(itemsbuf[directWpn>-1 ? directWpn : current_item_id(itype_sword)].usesound, pan(x.getInt()));
13315
13316
2/10
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
17 if(dowpn>-1 && itemsbuf[dowpn].script!=0 && !did_scripta && !(item_doscript[dowpn] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)))
13317 {
13318 if(!checkmagiccost(dowpn))
13319 {
13320 if(QMisc.miscsfx[sfxERROR])
13321 sfx(QMisc.miscsfx[sfxERROR]);
13322 }
13323 else
13324 {
13325 //clear the item script stack for a new script
13326
13327 ri = &(itemScriptData[dowpn]);
13328 for ( int32_t q = 0; q < 1024; q++ ) item_stack[dowpn][q] = 0xFFFF;
13329 ri->Clear();
13330 //itemScriptData[(dowpn & 0xFFF)].Clear();
13331 //for ( int32_t q = 0; q < 1024; q++ ) item_stack[(dowpn & 0xFFF)][q] = 0;
13332 //ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[dowpn].script, dowpn & 0xFFF);
13333 item_doscript[dowpn] = 1;
13334 itemscriptInitialised[dowpn] = 0;
13335 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[dowpn].script, dowpn);
13336 did_scripta=true;
13337 }
13338 }
13339 17 }
13340 else
13341 {
13342 if(QMisc.miscsfx[sfxERROR])
13343 sfx(QMisc.miscsfx[sfxERROR]);
13344 }
13345 17 }
13346 else
13347 {
13348 1506 did_scripta=false;
13349 }
13350
13351
5/10
✓ Branch 0 taken 1523 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1523 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1523 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1523 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1523 times.
1523 if(action!=swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking && !getOnSideviewLadder())
13352 {
13353
3/4
✓ Branch 0 taken 295 times.
✓ Branch 1 taken 1228 times.
✓ Branch 2 taken 295 times.
✗ Branch 3 not taken.
1523 if(DrunkUp() && canSideviewLadder())
13354 {
13355 setOnSideviewLadder(true);
13356 }
13357
3/4
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 1371 times.
✓ Branch 2 taken 152 times.
✗ Branch 3 not taken.
1523 else if(DrunkDown() && canSideviewLadder(true))
13358 {
13359 y+=1;
13360 setOnSideviewLadder(true);
13361 }
13362 1523 }
13363
13364 1523 int32_t wx=x;
13365 1523 int32_t wy=y;
13366
3/6
✓ Branch 0 taken 1220 times.
✓ Branch 1 taken 303 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1523 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1523 if((action==none || action==walking) && getOnSideviewLadder() && (get_bit(quest_rules,qr_SIDEVIEWLADDER_FACEUP)!=0)) //Allow DIR to change if standing still on sideview ladder, and force-face up.
13367 {
13368 if((xoff==0)||diagonalMovement)
13369 {
13370 if(DrunkUp()) dir=up;
13371 if(DrunkDown()) dir=down;
13372 }
13373
13374 if((yoff==0)||diagonalMovement)
13375 {
13376 if(DrunkLeft()) dir=left;
13377 if(DrunkRight()) dir=right;
13378 }
13379 }
13380
13381
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 363 times.
✓ Branch 2 taken 173 times.
✓ Branch 3 taken 399 times.
✓ Branch 4 taken 588 times.
1523 switch(dir)
13382 {
13383 case up:
13384 363 wy-=16;
13385 363 break;
13386
13387 case down:
13388 173 wy+=16;
13389 173 break;
13390
13391 case left:
13392 399 wx-=16;
13393 399 break;
13394
13395 case right:
13396 588 wx+=16;
13397 588 break;
13398 }
13399
13400 1523 do_lens();
13401
13402 1523 WalkflagInfo info;
13403
13404 1523 bool no_jinx = true;
13405
3/8
✓ Branch 0 taken 1481 times.
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1481 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1523 if(can_attack() && btnwpn>itype_sword && charging==0 && btnwpn!=itype_rupee) // This depends on item 0 being a rupee...
13406 {
13407 bool paidmagic = false;
13408 if(btnwpn==itype_wand && (directWpn>-1 ? (!item_disabled(directWpn) ? itemsbuf[directWpn].family==itype_wand : false) : current_item(itype_wand)))
13409 {
13410 attackid=directWpn>-1 ? directWpn : current_item_id(itype_wand);
13411 no_jinx = checkitem_jinx(attackid);
13412 if(no_jinx && checkbunny(attackid) && ((!(itemsbuf[attackid].flags & ITEM_FLAG6)) || checkmagiccost(attackid)))
13413 {
13414 if((itemsbuf[attackid].flags & ITEM_FLAG6) && !(misc_internal_hero_flags & LF_PAID_WAND_COST)){
13415 paymagiccost(attackid,true);
13416 misc_internal_hero_flags |= LF_PAID_WAND_COST;
13417 }
13418 SetAttack();
13419 attack=wWand;
13420 attackclk=0;
13421 }
13422 else
13423 {
13424 if(QMisc.miscsfx[sfxERROR])
13425 sfx(QMisc.miscsfx[sfxERROR]);
13426 }
13427 }
13428 else if((btnwpn==itype_hammer)&&!((action==attacking||action==sideswimattacking) && attack==wHammer)
13429 && (directWpn>-1 ? (!item_disabled(directWpn) ? itemsbuf[directWpn].family==itype_hammer : false) : current_item(itype_hammer)))
13430 {
13431 no_jinx = checkitem_jinx(dowpn);
13432 if(!(no_jinx && checkmagiccost(dowpn) && checkbunny(dowpn)))
13433 {
13434 if(QMisc.miscsfx[sfxERROR])
13435 sfx(QMisc.miscsfx[sfxERROR]);
13436 }
13437 else
13438 {
13439 paymagiccost(dowpn);
13440 paidmagic = true;
13441 SetAttack();
13442 attack=wHammer;
13443 attackid=directWpn>-1 ? directWpn : current_item_id(itype_hammer);
13444 attackclk=0;
13445 }
13446 }
13447 else if((btnwpn==itype_candle)&&!((action==attacking||action==sideswimattacking) && attack==wFire)
13448 && (directWpn>-1 ? (!item_disabled(directWpn) ? itemsbuf[directWpn].family==itype_candle : false) : current_item(itype_candle)))
13449 {
13450 //checkbunny handled where magic cost is paid
13451 attackid=directWpn>-1 ? directWpn : current_item_id(itype_candle);
13452 no_jinx = checkitem_jinx(attackid);
13453 if(no_jinx)
13454 {
13455 SetAttack();
13456 attack=wFire;
13457 attackclk=0;
13458 }
13459 }
13460 else if((btnwpn==itype_cbyrna)&&!((action==attacking||action==sideswimattacking) && attack==wCByrna)
13461 && (directWpn>-1 ? (!item_disabled(directWpn) ? itemsbuf[directWpn].family==itype_cbyrna : false) : current_item(itype_cbyrna)))
13462 {
13463 attackid=directWpn>-1 ? directWpn : current_item_id(itype_cbyrna);
13464 no_jinx = checkitem_jinx(attackid);
13465 if(no_jinx && checkbunny(attackid) && ((!(itemsbuf[attackid].flags & ITEM_FLAG6)) || checkmagiccost(attackid)))
13466 {
13467 if((itemsbuf[attackid].flags & ITEM_FLAG6) && !(misc_internal_hero_flags & LF_PAID_CBYRNA_COST)){
13468 paymagiccost(attackid,true);
13469 misc_internal_hero_flags |= LF_PAID_CBYRNA_COST;
13470 }
13471 SetAttack();
13472 attack=wCByrna;
13473 attackclk=0;
13474 }
13475 else
13476 {
13477 if(QMisc.miscsfx[sfxERROR])
13478 sfx(QMisc.miscsfx[sfxERROR]);
13479 }
13480 }
13481 else if((btnwpn==itype_bugnet)&&!((action==attacking||action==sideswimattacking) && attack==wBugNet)
13482 && (directWpn>-1 ? (!item_disabled(directWpn) && itemsbuf[directWpn].family==itype_bugnet) : current_item(itype_bugnet)))
13483 {
13484 attackid = directWpn>-1 ? directWpn : current_item_id(itype_bugnet);
13485 no_jinx = checkitem_jinx(attackid);
13486 if(no_jinx && checkbunny(attackid) && checkmagiccost(attackid))
13487 {
13488 paymagiccost(attackid);
13489 SetAttack();
13490 attack = wBugNet;
13491 attackclk = 0;
13492 sfx(itemsbuf[attackid].usesound);
13493 }
13494 else
13495 {
13496 if(QMisc.miscsfx[sfxERROR])
13497 sfx(QMisc.miscsfx[sfxERROR]);
13498 }
13499 }
13500 else
13501 {
13502 auto itmid = directWpn>-1 ? directWpn : current_item_id(btnwpn);
13503 no_jinx = checkitem_jinx(itmid);
13504 if(no_jinx)
13505 {
13506 paidmagic = startwpn(itmid);
13507
13508 if(paidmagic)
13509 {
13510 if(action==casting || action==drowning || action==lavadrowning || action == sideswimcasting || action==sidedrowning)
13511 {
13512 ;
13513 }
13514 else
13515 {
13516 SetAttack();
13517 attackclk=0;
13518 attack=none;
13519
13520 if(btnwpn==itype_brang)
13521 {
13522 attack=wBrang;
13523 }
13524 }
13525 }
13526 else
13527 {
13528 // Weapon not started: directWpn should be reset to prev. value.
13529 directWpn = olddirectwpn;
13530 }
13531 }
13532 }
13533
13534 if(dowpn>-1 && no_jinx && itemsbuf[dowpn].script!=0 && !did_scriptb && !(item_doscript[dowpn] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)))
13535 {
13536 if(!((paidmagic || checkmagiccost(dowpn)) && checkbunny(dowpn)))
13537 {
13538 if(QMisc.miscsfx[sfxERROR])
13539 sfx(QMisc.miscsfx[sfxERROR]);
13540 }
13541 else
13542 {
13543 // Only charge for magic if item's magic cost wasn't already charged
13544 // for the item's main use.
13545 if(!paidmagic && attack!=wWand)
13546 paymagiccost(dowpn);
13547 //clear the item script stack for a new script
13548 //itemScriptData[(dowpn & 0xFFF)].Clear();
13549 ri = &(itemScriptData[dowpn]);
13550 for ( int32_t q = 0; q < 1024; q++ ) item_stack[dowpn][q] = 0xFFFF;
13551 ri->Clear();
13552 //for ( int32_t q = 0; q < 1024; q++ ) item_stack[(dowpn & 0xFFF)][q] = 0;
13553 //ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[dowpn].script, dowpn & 0xFFF);
13554 item_doscript[dowpn] = 1;
13555 itemscriptInitialised[dowpn] = 0;
13556 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[dowpn].script, dowpn);
13557 did_scriptb=true;
13558 }
13559 }
13560
13561 if(no_jinx && (action==casting || action==drowning || action==lavadrowning || action == sideswimcasting || action==sidedrowning))
13562 {
13563 return;
13564 }
13565 if(!no_jinx)
13566 did_scriptb = false;
13567 }
13568 else
13569 {
13570 1523 did_scriptb=false;
13571 }
13572
13573
5/6
✓ Branch 0 taken 1285 times.
✓ Branch 1 taken 238 times.
✓ Branch 2 taken 1268 times.
✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1268 times.
1523 if(attackclk || action==attacking || action==sideswimattacking)
13574 {
13575
13576
4/8
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 238 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
255 if((attackclk==0) && action!=sideswimattacking && getOnSideviewLadder() && (get_bit(quest_rules,qr_SIDEVIEWLADDER_FACEUP)!=0)) //Allow DIR to change if standing still on sideview ladder, and force-face up.
13577 {
13578 if((xoff==0)||diagonalMovement)
13579 {
13580 if(DrunkUp()) dir=up;
13581 if(DrunkDown()) dir=down;
13582 }
13583
13584 if((yoff==0)||diagonalMovement)
13585 {
13586 if(DrunkLeft()) dir=left;
13587 if(DrunkRight()) dir=right;
13588 }
13589 }
13590
13591 255 bool attacked = doattack();
13592
13593 // This section below interferes with script-setting Hero->Dir, so it comes after doattack
13594
8/12
✓ Branch 0 taken 255 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 187 times.
✓ Branch 3 taken 68 times.
✓ Branch 4 taken 34 times.
✓ Branch 5 taken 153 times.
✓ Branch 6 taken 34 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 34 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 34 times.
255 if(!inlikelike && attackclk>4 && (attackclk&3)==0 && charging==0 && spins==0 && action!=sideswimattacking)
13595 {
13596
3/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
34 if((xoff==0)||diagonalMovement)
13597 {
13598
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if(DrunkUp()) dir=up;
13599
13600
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 if(DrunkDown()) dir=down;
13601 12 }
13602
13603
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
34 if((yoff==0)||diagonalMovement)
13604 {
13605
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 8 times.
30 if(DrunkLeft()) dir=left;
13606
13607
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6 times.
30 if(DrunkRight()) dir=right;
13608 30 }
13609 34 }
13610
13611
6/10
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 238 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 238 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 238 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 238 times.
255 if(attacked && (charging==0 && spins<=5) && jumping<1 && action!=sideswimattacking)
13612 {
13613 238 return;
13614 }
13615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if(!(attacked))
13616 {
13617 // Spin attack - change direction
13618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if(spins>1)
13619 {
13620 spins--;
13621
13622 if(spins%5==0)
13623 sfx(itemsbuf[current_item_id(spins >5 ? itype_spinscroll2 : itype_spinscroll)].usesound,pan(x.getInt()));
13624
13625 attackclk=1;
13626
13627 switch(dir)
13628 {
13629 case up:
13630 dir=left;
13631 break;
13632
13633 case right:
13634 dir=up;
13635 break;
13636
13637 case down:
13638 dir=right;
13639 break;
13640
13641 case left:
13642 dir=down;
13643 break;
13644 }
13645
13646 return;
13647 }
13648 else
13649 {
13650 17 spins=0;
13651 }
13652
13653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (IsSideSwim()) {action=sideswimming; FFCore.setHeroAction(sideswimming);}
13654 17 else {action=none; FFCore.setHeroAction(none);}
13655 17 attackclk=0;
13656 17 charging=0;
13657 17 }
13658 17 }
13659
13660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1285 times.
1285 if(pitslide()) //Check pit's 'pull'. If true, then Hero cannot fight the pull.
13661 return;
13662
13663
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 965 times.
1285 if(action==walking) //still walking
13664 {
13665
9/10
✓ Branch 0 taken 703 times.
✓ Branch 1 taken 262 times.
✓ Branch 2 taken 574 times.
✓ Branch 3 taken 129 times.
✓ Branch 4 taken 363 times.
✓ Branch 5 taken 211 times.
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 354 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 9 times.
965 if(!DrunkUp() && !DrunkDown() && !DrunkLeft() && !DrunkRight() && !autostep)
13666 {
13667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if(attackclk>0) SetAttack();
13668 9 else {action = none; FFCore.setHeroAction(none);}
13669 9 hero_count=-1;
13670 9 return;
13671 }
13672
13673 956 autostep=false;
13674
13675
2/4
✓ Branch 0 taken 956 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 956 times.
956 if(!(diagonalMovement || NO_GRIDLOCK))
13676 {
13677
2/4
✓ Branch 0 taken 956 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 956 times.
956 if(get_bit(quest_rules, qr_NEW_HERO_MOVEMENT) || IsSideSwim())
13678 {
13679 if(dir==up&&yoff)
13680 {
13681 info = walkflag(x,y+(bigHitbox?0:8)-int32_t(lsteps[y.getInt()&7]),2,up);
13682 info = info || walkflagMBlock(x+8,y+(bigHitbox?0:8)-int32_t(lsteps[y.getInt()&7]));
13683 execute(info);
13684
13685 if(!info.isUnwalkable())
13686 {
13687 move(up);
13688 }
13689 else
13690 {
13691 action=none; FFCore.setHeroAction(none);
13692 }
13693
13694 return;
13695 }
13696
13697 if(dir==down&&yoff)
13698 {
13699 info = walkflag(x,y+15+int32_t(lsteps[y.getInt()&7]),2,down);
13700 info = info || walkflagMBlock(x+8,y+15+int32_t(lsteps[y.getInt()&7]));
13701 execute(info);
13702
13703 if(!info.isUnwalkable())
13704 {
13705 move(down);
13706 }
13707 else
13708 {
13709 action=none; FFCore.setHeroAction(none);
13710 }
13711
13712 return;
13713 }
13714
13715 if(dir==left&&xoff)
13716 {
13717 info = walkflag(x-int32_t(lsteps[x.getInt()&7]),y+(bigHitbox?0:8),1,left) || walkflag(x-int32_t(lsteps[x.getInt()&7]),y+8,1,left);
13718 execute(info);
13719
13720 if(!info.isUnwalkable())
13721 {
13722 move(left);
13723 }
13724 else
13725 {
13726 action=none; FFCore.setHeroAction(none);
13727 }
13728
13729 return;
13730 }
13731
13732 if(dir==right&&xoff)
13733 {
13734 info = walkflag(x+15+int32_t(lsteps[x.getInt()&7]),y+(bigHitbox?0:8),1,right) || walkflag(x+15+int32_t(lsteps[x.getInt()&7]),y+8,1,right);
13735 execute(info);
13736
13737 if(!info.isUnwalkable())
13738 {
13739 move(right);
13740 }
13741 else
13742 {
13743 action=none; FFCore.setHeroAction(none);
13744 }
13745
13746 return;
13747 }
13748 }
13749 else
13750 {
13751
4/4
✓ Branch 0 taken 253 times.
✓ Branch 1 taken 703 times.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 212 times.
956 if(dir==up&&yoff)
13752 {
13753 212 while(true)
13754 {
13755 212 info = walkflag(temp_x,temp_y+(bigHitbox?0:8)-temp_step,2,up);
13756 212 info = info || walkflagMBlock(temp_x+8,temp_y+(bigHitbox?0:8)-temp_step);
13757 212 execute(info);
13758
13759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 212 times.
212 if(!info.isUnwalkable())
13760 {
13761 212 hero_newstep = temp_step;
13762 212 x = temp_x;
13763 212 y = temp_y;
13764 212 move(up);
13765 212 return;
13766 }
13767 //Could not move, try moving less
13768 if(temp_y != int32_t(temp_y))
13769 {
13770 temp_y = floor((double)temp_y);
13771 continue;
13772 }
13773 else if(temp_step > 1)
13774 {
13775 if(temp_step != int32_t(temp_step)) //floor
13776 temp_step = floor((double)temp_step);
13777 else --temp_step;
13778 continue;
13779 }
13780 else //Can't move less, stop moving
13781 {
13782 action=none; FFCore.setHeroAction(none);
13783 }
13784 return;
13785 }
13786 }
13787
13788
4/4
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 609 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 112 times.
744 if(dir==down&&yoff)
13789 {
13790 112 while(true)
13791 {
13792 113 info = walkflag(temp_x,temp_y+15+temp_step,2,down);
13793 113 info = info || walkflagMBlock(temp_x+8,temp_y+15+temp_step);
13794 113 execute(info);
13795
13796
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 112 times.
113 if(!info.isUnwalkable())
13797 {
13798 112 hero_newstep = temp_step;
13799 112 x = temp_x;
13800 112 y = temp_y;
13801 112 move(down);
13802 112 return;
13803 }
13804 //Could not move, try moving less
13805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(temp_y != int32_t(temp_y))
13806 {
13807 temp_y = floor((double)temp_y);
13808 continue;
13809 }
13810
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if(temp_step > 1)
13811 {
13812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(temp_step != int32_t(temp_step)) //floor
13813 1 temp_step = floor((double)temp_step);
13814 else --temp_step;
13815 1 continue;
13816 }
13817 else //Can't move less, stop moving
13818 {
13819 action=none; FFCore.setHeroAction(none);
13820 }
13821 return;
13822 }
13823 }
13824
13825
4/4
✓ Branch 0 taken 225 times.
✓ Branch 1 taken 407 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 185 times.
632 if(dir==left&&xoff)
13826 {
13827 185 while(true)
13828 {
13829 185 info = walkflag(temp_x-temp_step,temp_y+(bigHitbox?0:8),1,left) || walkflag(temp_x-temp_step,temp_y+8,1,left);
13830 185 execute(info);
13831
13832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 185 times.
185 if(!info.isUnwalkable())
13833 {
13834 185 hero_newstep = temp_step;
13835 185 x = temp_x;
13836 185 y = temp_y;
13837 185 move(left);
13838 185 return;
13839 }
13840 //Could not move, try moving less
13841 if(temp_x != int32_t(temp_x))
13842 {
13843 temp_x = floor((double)temp_x);
13844 continue;
13845 }
13846 else if(temp_step > 1)
13847 {
13848 if(temp_step != int32_t(temp_step)) //floor
13849 temp_step = floor((double)temp_step);
13850 else --temp_step;
13851 continue;
13852 }
13853 else //Can't move less, stop moving
13854 {
13855 action=none; FFCore.setHeroAction(none);
13856 }
13857 return;
13858 }
13859 }
13860
13861
4/4
✓ Branch 0 taken 343 times.
✓ Branch 1 taken 104 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 289 times.
447 if(dir==right&&xoff)
13862 {
13863 289 while(true)
13864 {
13865 289 info = walkflag(temp_x+15+temp_step,temp_y+(bigHitbox?0:8),1,right) || walkflag(temp_x+15+temp_step,temp_y+8,1,right);
13866 289 execute(info);
13867
13868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 289 times.
289 if(!info.isUnwalkable())
13869 {
13870 289 hero_newstep = temp_step;
13871 289 x = temp_x;
13872 289 y = temp_y;
13873 289 move(right);
13874 289 return;
13875 }
13876 //Could not move, try moving less
13877 if(temp_x != int32_t(temp_x))
13878 {
13879 temp_x = floor((double)temp_x);
13880 continue;
13881 }
13882 else if(temp_step > 1)
13883 {
13884 if(temp_step != int32_t(temp_step)) //floor
13885 temp_step = floor((double)temp_step);
13886 else --temp_step;
13887 continue;
13888 }
13889 else //Can't move less, stop moving
13890 {
13891 action=none; FFCore.setHeroAction(none);
13892 }
13893 return;
13894 }
13895 }
13896 }
13897 158 }
13898
13899 158 } // endif (action==walking)
13900
13901
12/24
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 478 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 478 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 478 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 478 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 478 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 478 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 478 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 478 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 478 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 478 times.
478 if((action!=swimming)&&(action!=sideswimming)&&(action !=sideswimhit)&&(action !=sideswimattacking)&&(action!=casting)&&(action!=sideswimcasting)&&(action!=drowning)&&(action!=sidedrowning)&&(action!=lavadrowning) && charging==0 && spins==0 && jumping<1)
13902 {
13903 478 action=none; FFCore.setHeroAction(none);
13904 478 }
13905
13906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
478 if(diagonalMovement)
13907 {
13908 switch(holddir)
13909 {
13910 case up:
13911 if(!Up())
13912 {
13913 holddir=-1;
13914 }
13915
13916 break;
13917
13918 case down:
13919 if(!Down())
13920 {
13921 holddir=-1;
13922 }
13923
13924 break;
13925
13926 case left:
13927 if(!Left())
13928 {
13929 holddir=-1;
13930 }
13931
13932 break;
13933
13934 case right:
13935 if(!Right())
13936 {
13937 holddir=-1;
13938 }
13939
13940 break;
13941
13942 default:
13943 break;
13944 } //end switch
13945
13946 if(get_bit(quest_rules, qr_NEW_HERO_MOVEMENT) || IsSideSwim()) //!DIRECTION SET
13947 {
13948 walkable = false;
13949 if(DrunkUp()&&(holddir==-1||holddir==up))
13950 {
13951 if(isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM) && !toogam)
13952 {
13953 }
13954 else
13955 {
13956 if(charging==0 && spins==0 && action != sideswimattacking && !(IsSideSwim() && get_bit(quest_rules,qr_SIDESWIMDIR)))
13957 {
13958 dir=up;
13959 }
13960
13961 holddir=up;
13962
13963 if(DrunkRight()&&shiftdir!=left)
13964 {
13965 shiftdir=right;
13966 if (IsSideSwim() && get_bit(quest_rules,qr_SIDESWIMDIR) && (charging==0 && spins==0)) dir = right;
13967 if (!IsSideSwim() || (charging==0 && spins==0)) sideswimdir = right;
13968 }
13969 else if(DrunkLeft()&&shiftdir!=right)
13970 {
13971 shiftdir=left;
13972 if (IsSideSwim() && get_bit(quest_rules,qr_SIDESWIMDIR) && (charging==0 && spins==0)) dir = left;
13973 if (!IsSideSwim() || (charging==0 && spins==0)) sideswimdir = left;
13974 }
13975 else
13976 {
13977 shiftdir=-1;
13978 }
13979
13980 //walkable if Ladder can be placed or is already placed vertically
13981 if(isSideViewHero() && !toogam && (!get_bit(quest_rules, qr_OLD_LADDER_ITEM_SIDEVIEW) || !(can_deploy_ladder() || (ladderx && laddery && ladderdir==up))) && !getOnSideviewLadder() && action != sideswimming && action != sideswimhit && action != sideswimattacking)
13982 {
13983 walkable=false;
13984 }
13985 else
13986 {
13987 do
13988 {
13989 info = walkflag(x,(bigHitbox?0:8)+(y-hero_newstep),2,up);
13990
13991 info = info || walkflag(x+15,(bigHitbox?0:8)+(y-hero_newstep),1,up);
13992 info = info || walkflagMBlock(x+15, (bigHitbox?0:8)+(y-hero_newstep));
13993
13994 execute(info);
13995
13996 if(info.isUnwalkable())
13997 {
13998 if(y != y.getInt())
13999 {
14000 y.doRound();
14001 }
14002 else if(hero_newstep > 1)
14003 {
14004 if(hero_newstep != int32_t(hero_newstep)) //floor
14005 hero_newstep = floor((double)hero_newstep);
14006 else --hero_newstep;
14007 }
14008 else
14009 break;
14010 }
14011 else walkable = true;
14012 }
14013 while(!walkable);
14014 }
14015
14016 int32_t s=shiftdir;
14017
14018 if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM))
14019 {
14020 shiftdir=-1;
14021 }
14022 else
14023 {
14024 if(s==left)
14025 {
14026 do
14027 {
14028 info = (walkflag(x-hero_newstep_diag,y+(bigHitbox?0:8),1,left)||walkflag(x-hero_newstep_diag,y+15,1,left));
14029
14030 execute(info);
14031
14032 if(info.isUnwalkable())
14033 {
14034 if(x != x.getInt())
14035 {
14036 x.doRound();
14037 }
14038 else if(hero_newstep_diag > 1)
14039 {
14040 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14041 hero_newstep_diag.doFloor();
14042 else --hero_newstep_diag;
14043 }
14044 else
14045 shiftdir = -1;
14046 }
14047 else if(walkable)
14048 {
14049 do
14050 {
14051 info = walkflag(x-hero_newstep_diag,(bigHitbox?0:8)+(y-hero_newstep),1,left);
14052 execute(info);
14053 if(info.isUnwalkable())
14054 {
14055 if(x != x.getInt())
14056 {
14057 x.doRound();
14058 }
14059 else if(hero_newstep_diag > 1)
14060 {
14061 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14062 hero_newstep_diag.doFloor();
14063 else --hero_newstep_diag;
14064 }
14065 else
14066 shiftdir = -1;
14067 }
14068 else break;
14069 }
14070 while(shiftdir != -1);
14071 break;
14072 }
14073 else break;
14074 }
14075 while(shiftdir != -1);
14076 }
14077 else if(s==right)
14078 {
14079 do
14080 {
14081 info = (walkflag(x+15+hero_newstep_diag,y+(bigHitbox?0:8),1,right)||walkflag(x+15+hero_newstep_diag,y+15,1,right));
14082
14083 execute(info);
14084
14085 if(info.isUnwalkable())
14086 {
14087 if(x != x.getInt())
14088 {
14089 x.doRound();
14090 }
14091 else if(hero_newstep_diag > 1)
14092 {
14093 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14094 hero_newstep_diag.doFloor();
14095 else --hero_newstep_diag;
14096 }
14097 else
14098 shiftdir = -1;
14099 }
14100 else if(walkable)
14101 {
14102 do
14103 {
14104 info = walkflag(x+15+hero_newstep_diag,(bigHitbox?0:8)+(y-hero_newstep),1,right);
14105 execute(info);
14106 if(info.isUnwalkable())
14107 {
14108 if(x != x.getInt())
14109 {
14110 x.doRound();
14111 }
14112 else if(hero_newstep_diag > 1)
14113 {
14114 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14115 hero_newstep_diag.doFloor();
14116 else --hero_newstep_diag;
14117 }
14118 else
14119 shiftdir = -1;
14120 }
14121 else break;
14122 }
14123 while(shiftdir != -1);
14124 break;
14125 }
14126 else break;
14127 }
14128 while(shiftdir != -1);
14129 }
14130 }
14131
14132 move(up);
14133 shiftdir=s;
14134
14135 if(!walkable)
14136 {
14137 if(shiftdir==-1) //Corner-shove; prevent being stuck on corners -V
14138 {
14139 x = x.getInt();
14140 y = y.getInt();
14141 if(!_walkflag(x,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
14142 !_walkflag(x+8, y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
14143 _walkflag(x+15,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE))
14144 {
14145 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+15,y+(bigHitbox?0:8)-1))
14146 sprite::move((zfix)-1,(zfix)0);
14147 }
14148 else
14149 {
14150 if(_walkflag(x, y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
14151 !_walkflag(x+7, y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
14152 !_walkflag(x+15,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE))
14153 {
14154 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x,y+(bigHitbox?0:8)-1))
14155 sprite::move((zfix)1,(zfix)0);
14156 }
14157 else
14158 {
14159 pushing=push+1;
14160 }
14161 }
14162 }
14163 else
14164 {
14165 pushing=push+1; // L: This makes solid damage combos and diagonal-triggered Armoses work.
14166 }
14167 }
14168
14169 return;
14170 }
14171 }
14172
14173 if(DrunkDown()&&(holddir==-1||holddir==down))
14174 {
14175 if(isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM) && !toogam)
14176 {
14177 }
14178 else
14179 {
14180 if(charging==0 && spins==0 && action != sideswimattacking && !(IsSideSwim() && get_bit(quest_rules,qr_SIDESWIMDIR)))
14181 {
14182 dir=down;
14183 }
14184
14185 holddir=down;
14186
14187 if(DrunkRight()&&shiftdir!=left)
14188 {
14189 shiftdir=right;
14190 if (IsSideSwim() && get_bit(quest_rules,qr_SIDESWIMDIR) && (charging==0 && spins==0)) dir = right;
14191 if (!IsSideSwim() || (charging==0 && spins==0)) sideswimdir = right;
14192 }
14193 else if(DrunkLeft()&&shiftdir!=right)
14194 {
14195 shiftdir=left;
14196 if (IsSideSwim() && get_bit(quest_rules,qr_SIDESWIMDIR) && (charging==0 && spins==0)) dir = left;
14197 if (!IsSideSwim() || (charging==0 && spins==0)) sideswimdir = left;
14198 }
14199 else
14200 {
14201 shiftdir=-1;
14202 }
14203
14204 //bool walkable;
14205 if(isSideViewHero() && !toogam && !getOnSideviewLadder() && action != sideswimming && action != sideswimhit && action != sideswimattacking)
14206 {
14207 walkable=false;
14208 }
14209 else
14210 {
14211 do
14212 {
14213 info = walkflag(x,15+(y+hero_newstep),2,down);
14214
14215 if(x.getFloor() & 7)
14216 info = info || walkflag(x+15,15+(y+hero_newstep),1,down);
14217 else
14218 info = info || walkflagMBlock(x+15, 15+(y+hero_newstep));
14219
14220 execute(info);
14221
14222 if(info.isUnwalkable())
14223 {
14224 if(y != y.getInt())
14225 {
14226 y.doRound();
14227 }
14228 else if(hero_newstep > 1)
14229 {
14230 if(hero_newstep != int32_t(hero_newstep)) //floor
14231 hero_newstep = floor((double)hero_newstep);
14232 else --hero_newstep;
14233 }
14234 else
14235 break;
14236 }
14237 else walkable = true;
14238 }
14239 while(!walkable);
14240 }
14241
14242 int32_t s=shiftdir;
14243
14244 if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM))
14245 {
14246 shiftdir=-1;
14247 }
14248 else
14249 {
14250 if(s==left)
14251 {
14252 do
14253 {
14254 info = (walkflag(x-hero_newstep_diag,y+(bigHitbox?0:8),1,left)||walkflag(x-hero_newstep_diag,y+15,1,left));
14255
14256 execute(info);
14257
14258 if(info.isUnwalkable())
14259 {
14260 if(x != x.getInt())
14261 {
14262 x.doRound();
14263 }
14264 else if(hero_newstep_diag > 1)
14265 {
14266 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14267 hero_newstep_diag.doFloor();
14268 else --hero_newstep_diag;
14269 }
14270 else
14271 shiftdir = -1;
14272 }
14273 else if(walkable)
14274 {
14275 do
14276 {
14277 info = walkflag(x-hero_newstep_diag,15+(y+hero_newstep),1,left);
14278 execute(info);
14279 if(info.isUnwalkable())
14280 {
14281 if(x != x.getInt())
14282 {
14283 x.doRound();
14284 }
14285 else if(hero_newstep_diag > 1)
14286 {
14287 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14288 hero_newstep_diag.doFloor();
14289 else --hero_newstep_diag;
14290 }
14291 else
14292 shiftdir = -1;
14293 }
14294 else break;
14295 }
14296 while(shiftdir != -1);
14297 break;
14298 }
14299 else break;
14300 }
14301 while(shiftdir != -1);
14302 }
14303 else if(s==right)
14304 {
14305 do
14306 {
14307 info = (walkflag(x+15+hero_newstep_diag,y+(bigHitbox?0:8),1,right)||walkflag(x+15+hero_newstep_diag,y+15,1,right));
14308
14309 execute(info);
14310
14311 if(info.isUnwalkable())
14312 {
14313 if(x != x.getInt())
14314 {
14315 x.doRound();
14316 }
14317 else if(hero_newstep_diag > 1)
14318 {
14319 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14320 hero_newstep_diag.doFloor();
14321 else --hero_newstep_diag;
14322 }
14323 else
14324 shiftdir = -1;
14325 }
14326 else if(walkable)
14327 {
14328 do
14329 {
14330 info = walkflag(x+15+hero_newstep_diag,15+(y+hero_newstep),1,right);
14331 execute(info);
14332 if(info.isUnwalkable())
14333 {
14334 if(x != x.getInt())
14335 {
14336 x.doRound();
14337 }
14338 else if(hero_newstep_diag > 1)
14339 {
14340 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14341 hero_newstep_diag.doFloor();
14342 else --hero_newstep_diag;
14343 }
14344 else
14345 shiftdir = -1;
14346 }
14347 else break;
14348 }
14349 while(shiftdir != -1);
14350 break;
14351 }
14352 else break;
14353 }
14354 while(shiftdir != -1);
14355 }
14356 }
14357
14358 move(down);
14359 shiftdir=s;
14360
14361 if(!walkable)
14362 {
14363 if(shiftdir==-1) //Corner-shove; prevent being stuck on corners -V
14364 {
14365 x = x.getInt();
14366 y = y.getInt();
14367 if(!_walkflag(x, y+15+1,1,SWITCHBLOCK_STATE)&&
14368 !_walkflag(x+8, y+15+1,1,SWITCHBLOCK_STATE)&&
14369 _walkflag(x+15,y+15+1,1,SWITCHBLOCK_STATE))
14370 {
14371 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+15,y+15+1))
14372 sprite::move((zfix)-1,(zfix)0);
14373 }
14374 else if(_walkflag(x, y+15+1,1,SWITCHBLOCK_STATE)&&
14375 !_walkflag(x+7, y+15+1,1,SWITCHBLOCK_STATE)&&
14376 !_walkflag(x+15,y+15+1,1,SWITCHBLOCK_STATE))
14377 {
14378 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x,y+15+1))
14379 sprite::move((zfix)1,(zfix)0);
14380 }
14381 else
14382 {
14383 pushing=push+1;
14384 }
14385 }
14386 else
14387 {
14388 pushing=push+1; // L: This makes solid damage combos and diagonal-triggered Armoses work.
14389 }
14390 }
14391
14392 return;
14393 }
14394 }
14395
14396 if(DrunkLeft()&&(holddir==-1||holddir==left))
14397 {
14398 if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM) && !toogam)
14399 {
14400 }
14401 else
14402 {
14403 if(charging==0 && spins==0 && action != sideswimattacking)
14404 {
14405 dir=left;
14406 }
14407 sideswimdir = left;
14408
14409 holddir=left;
14410
14411 if(DrunkUp()&&shiftdir!=down)
14412 {
14413 shiftdir=up;
14414 }
14415 else if(DrunkDown()&&shiftdir!=up)
14416 {
14417 shiftdir=down;
14418 }
14419 else
14420 {
14421 shiftdir=-1;
14422 }
14423
14424 do
14425 {
14426 info = walkflag(x-hero_newstep,y+(bigHitbox?0:8),1,left)||walkflag(x-hero_newstep,y+8,1,left);
14427
14428 info = info || walkflag(x-hero_newstep,y+15,1,left);
14429
14430 execute(info);
14431
14432 if(info.isUnwalkable())
14433 {
14434 if(x != x.getInt())
14435 {
14436 x.doRound();
14437 }
14438 else if(hero_newstep > 1)
14439 {
14440 if(hero_newstep != int32_t(hero_newstep)) //floor
14441 hero_newstep = floor((double)hero_newstep);
14442 else --hero_newstep;
14443 }
14444 else
14445 break;
14446 }
14447 else walkable = true;
14448 }
14449 while(!walkable);
14450
14451 int32_t s=shiftdir;
14452
14453 if((isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM)) || (isSideViewHero() && !getOnSideviewLadder() && action != sideswimming && action != sideswimhit && action != sideswimattacking))
14454 {
14455 shiftdir=-1;
14456 }
14457 else
14458 {
14459 if(s==up)
14460 {
14461 do
14462 {
14463 info = walkflag(x,y+(bigHitbox?0:8)-hero_newstep_diag,2,up)||walkflag(x+15,y+(bigHitbox?0:8)-hero_newstep_diag,1,up);
14464
14465 execute(info);
14466
14467 if(info.isUnwalkable())
14468 {
14469 if(y != y.getInt())
14470 {
14471 y.doRound();
14472 }
14473 else if(hero_newstep_diag > 1)
14474 {
14475 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14476 hero_newstep_diag.doFloor();
14477 else --hero_newstep_diag;
14478 }
14479 else
14480 shiftdir = -1;
14481 }
14482 else if(walkable)
14483 {
14484 do
14485 {
14486 info = walkflag(x-hero_newstep,y+(bigHitbox?0:8)-hero_newstep_diag,1,up);
14487 execute(info);
14488 if(info.isUnwalkable())
14489 {
14490 if(y != y.getInt())
14491 {
14492 y.doRound();
14493 }
14494 else if(hero_newstep_diag > 1)
14495 {
14496 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14497 hero_newstep_diag.doFloor();
14498 else --hero_newstep_diag;
14499 }
14500 else
14501 shiftdir = -1;
14502 }
14503 else break;
14504 }
14505 while(shiftdir != -1);
14506 break;
14507 }
14508 else break;
14509 }
14510 while(shiftdir != -1);
14511 }
14512 else if(s==down)
14513 {
14514 do
14515 {
14516 info = walkflag(x,y+15+hero_newstep_diag,2,down)||walkflag(x+15,y+15+hero_newstep_diag,1,down);
14517
14518 execute(info);
14519
14520 if(info.isUnwalkable())
14521 {
14522 if(y != y.getInt())
14523 {
14524 y.doRound();
14525 }
14526 else if(hero_newstep_diag > 1)
14527 {
14528 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14529 hero_newstep_diag.doFloor();
14530 else --hero_newstep_diag;
14531 }
14532 else
14533 shiftdir = -1;
14534 }
14535 else if(walkable)
14536 {
14537 do
14538 {
14539 info = walkflag(x-hero_newstep,y+15+hero_newstep_diag,1,down);
14540 execute(info);
14541 if(info.isUnwalkable())
14542 {
14543 if(y != y.getInt())
14544 {
14545 y.doRound();
14546 }
14547 else if(hero_newstep_diag > 1)
14548 {
14549 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14550 hero_newstep_diag.doFloor();
14551 else --hero_newstep_diag;
14552 }
14553 else
14554 shiftdir = -1;
14555 }
14556 else break;
14557 }
14558 while(shiftdir != -1);
14559 break;
14560 }
14561 else break;
14562 }
14563 while(shiftdir != -1);
14564 }
14565 }
14566
14567 move(left);
14568 shiftdir=s;
14569
14570 if(!walkable)
14571 {
14572 if(shiftdir==-1) //Corner-shove; prevent being stuck on corners -V
14573 {
14574 x = x.getInt();
14575 y = y.getInt();
14576 int32_t v1=bigHitbox?0:8;
14577 int32_t v2=bigHitbox?8:12;
14578
14579 if(!_walkflag(x-1,y+v1,1,SWITCHBLOCK_STATE)&&
14580 !_walkflag(x-1,y+v2,1,SWITCHBLOCK_STATE)&&
14581 _walkflag(x-1,y+15,1,SWITCHBLOCK_STATE))
14582 {
14583 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x-1,y+15))
14584 sprite::move((zfix)0,(zfix)-1);
14585 }
14586 else if(_walkflag(x-1,y+v1, 1,SWITCHBLOCK_STATE)&&
14587 !_walkflag(x-1,y+v2-1,1,SWITCHBLOCK_STATE)&&
14588 !_walkflag(x-1,y+15, 1,SWITCHBLOCK_STATE))
14589 {
14590 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x-1,y+v1))
14591 sprite::move((zfix)0,(zfix)1);
14592 }
14593 else
14594 {
14595 pushing=push+1;
14596 }
14597 }
14598 else
14599 {
14600 pushing=push+1; // L: This makes solid damage combos and diagonal-triggered Armoses work.
14601
14602 if(action!=swimming)
14603 {
14604 }
14605 }
14606 }
14607
14608 return;
14609 }
14610 }
14611
14612 if(DrunkRight()&&(holddir==-1||holddir==right))
14613 {
14614 if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM) && !toogam)
14615 {
14616 }
14617 else
14618 {
14619 if(charging==0 && spins==0 && action != sideswimattacking)
14620 {
14621 dir=right;
14622 }
14623 sideswimdir = right;
14624
14625 holddir=right;
14626
14627 if(DrunkUp()&&shiftdir!=down)
14628 {
14629 shiftdir=up;
14630 }
14631 else if(DrunkDown()&&shiftdir!=up)
14632 {
14633 shiftdir=down;
14634 }
14635 else
14636 {
14637 shiftdir=-1;
14638 }
14639
14640 do
14641 {
14642 info = walkflag(x+15+hero_newstep,y+(bigHitbox?0:8),1,right)||walkflag(x+15+hero_newstep,y+8,1,right);;
14643
14644 info = info || walkflag(x+15+hero_newstep,y+15,1,right);
14645
14646 execute(info);
14647
14648 if(info.isUnwalkable())
14649 {
14650 if(x != x.getInt())
14651 {
14652 x.doRound();
14653 }
14654 else if(hero_newstep > 1)
14655 {
14656 if(hero_newstep != int32_t(hero_newstep)) //floor
14657 hero_newstep = floor((double)hero_newstep);
14658 else --hero_newstep;
14659 }
14660 else
14661 break;
14662 }
14663 else walkable = true;
14664 }
14665 while(!walkable);
14666
14667 int32_t s=shiftdir;
14668
14669 if((isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM)) || (isSideViewHero() && !getOnSideviewLadder() && action != sideswimming && action != sideswimhit && action != sideswimattacking))
14670 {
14671 shiftdir=-1;
14672 }
14673 else
14674 {
14675 if(s==up)
14676 {
14677 do
14678 {
14679 info = walkflag(x,y+(bigHitbox?0:8)-hero_newstep_diag,2,up)||walkflag(x+15,y+(bigHitbox?0:8)-hero_newstep_diag,1,up);
14680
14681 execute(info);
14682
14683 if(info.isUnwalkable())
14684 {
14685 if(y != y.getInt())
14686 {
14687 y.doRound();
14688 }
14689 else if(hero_newstep_diag > 1)
14690 {
14691 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14692 hero_newstep_diag.doFloor();
14693 else --hero_newstep_diag;
14694 }
14695 else
14696 shiftdir = -1;
14697 }
14698 else if(walkable)
14699 {
14700 do
14701 {
14702 info = walkflag(x+15+hero_newstep,y+(bigHitbox?0:8)-hero_newstep_diag,1,up);
14703 execute(info);
14704 if(info.isUnwalkable())
14705 {
14706 if(y != y.getInt())
14707 {
14708 y.doRound();
14709 }
14710 else if(hero_newstep_diag > 1)
14711 {
14712 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14713 hero_newstep_diag.doFloor();
14714 else --hero_newstep_diag;
14715 }
14716 else
14717 shiftdir = -1;
14718 }
14719 else break;
14720 }
14721 while(shiftdir != -1);
14722 break;
14723 }
14724 else break;
14725 }
14726 while(shiftdir != -1);
14727 }
14728 else if(s==down)
14729 {
14730 do
14731 {
14732 info = walkflag(x,y+15+hero_newstep_diag,2,down)||walkflag(x+15,y+15+hero_newstep_diag,1,down);
14733
14734 execute(info);
14735
14736 if(info.isUnwalkable())
14737 {
14738 if(y != y.getInt())
14739 {
14740 y.doRound();
14741 }
14742 else if(hero_newstep_diag > 1)
14743 {
14744 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14745 hero_newstep_diag.doFloor();
14746 else --hero_newstep_diag;
14747 }
14748 else
14749 shiftdir = -1;
14750 }
14751 else if(walkable)
14752 {
14753 do
14754 {
14755 info = walkflag(x+15+hero_newstep,y+15+hero_newstep_diag,1,down);
14756 execute(info);
14757 if(info.isUnwalkable())
14758 {
14759 if(y != y.getInt())
14760 {
14761 y.doRound();
14762 }
14763 else if(hero_newstep_diag > 1)
14764 {
14765 if(hero_newstep_diag != hero_newstep_diag.getInt()) //floor
14766 hero_newstep_diag.doFloor();
14767 else --hero_newstep_diag;
14768 }
14769 else
14770 shiftdir = -1;
14771 }
14772 else break;
14773 }
14774 while(shiftdir != -1);
14775 break;
14776 }
14777 else break;
14778 }
14779 while(shiftdir != -1);
14780 }
14781 }
14782
14783 move(right);
14784 shiftdir=s;
14785
14786 if(!walkable)
14787 {
14788 if(shiftdir==-1) //Corner-shove; prevent being stuck on corners -V
14789 {
14790 x = x.getInt();
14791 y = y.getInt();
14792 int32_t v1=bigHitbox?0:8;
14793 int32_t v2=bigHitbox?8:12;
14794
14795 if(!_walkflag(x+16,y+v1,1,SWITCHBLOCK_STATE)&&
14796 !_walkflag(x+16,y+v2,1,SWITCHBLOCK_STATE)&&
14797 _walkflag(x+16,y+15,1,SWITCHBLOCK_STATE))
14798 {
14799 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+16,y+15))
14800 sprite::move((zfix)0,(zfix)-1);
14801 }
14802 else if(_walkflag(x+16,y+v1,1,SWITCHBLOCK_STATE)&&
14803 !_walkflag(x+16,y+v2-1,1,SWITCHBLOCK_STATE)&&
14804 !_walkflag(x+16,y+15,1,SWITCHBLOCK_STATE))
14805 {
14806 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+16,y+v1))
14807 sprite::move((zfix)0,(zfix)1);
14808 }
14809 else
14810 {
14811 pushing=push+1;
14812 z3step=2;
14813 }
14814 }
14815 else
14816 {
14817 pushing=push+1; // L: This makes solid damage combos and diagonal-triggered Armoses work.
14818
14819 if(action!=swimming)
14820 {
14821 }
14822 }
14823 }
14824
14825 return;
14826 }
14827 }
14828 }
14829 else
14830 {
14831 if(DrunkUp()&&(holddir==-1||holddir==up))
14832 {
14833 if(isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM) && !toogam)
14834 {
14835 }
14836 else
14837 {
14838 if(charging==0 && spins==0)
14839 {
14840 dir=up;
14841 }
14842
14843 holddir=up;
14844
14845 if(DrunkRight()&&shiftdir!=left)
14846 {
14847 shiftdir=right;
14848 }
14849 else if(DrunkLeft()&&shiftdir!=right)
14850 {
14851 shiftdir=left;
14852 }
14853 else
14854 {
14855 shiftdir=-1;
14856 }
14857
14858 //walkable if Ladder can be placed or is already placed vertically
14859 if(isSideViewHero() && !toogam && !(can_deploy_ladder() || (ladderx && laddery && ladderdir==up)) && !getOnSideviewLadder() && action != sideswimming && action != sideswimhit && action != sideswimattacking)
14860 {
14861 walkable=false;
14862 }
14863 else
14864 {
14865 info = walkflag(x,y+(bigHitbox?0:8)-z3step,2,up);
14866
14867 if(x.getInt() & 7)
14868 info = info || walkflag(x+16,y+(bigHitbox?0:8)-z3step,1,up);
14869 else
14870 info = info || walkflagMBlock(x+16, y+(bigHitbox?0:8)-z3step);
14871
14872 execute(info);
14873
14874 if(info.isUnwalkable())
14875 {
14876 if(z3step==2)
14877 {
14878 z3step=1;
14879 info = walkflag(x,y+(bigHitbox?0:8)-z3step,2,up);
14880
14881 if(x.getInt()&7)
14882 info = info || walkflag(x+16,y+(bigHitbox?0:8)-z3step,1,up);
14883 else
14884 info = info || walkflagMBlock(x+16, y+(bigHitbox?0:8)-z3step);
14885
14886 execute(info);
14887
14888 if(info.isUnwalkable())
14889 {
14890 walkable = false;
14891 }
14892 else
14893 {
14894 walkable=true;
14895 }
14896 }
14897 else
14898 {
14899 walkable=false;
14900 }
14901 }
14902 else
14903 {
14904 walkable = true;
14905 }
14906 }
14907
14908 int32_t s=shiftdir;
14909
14910 if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM))
14911 {
14912 shiftdir=-1;
14913 }
14914 else
14915 {
14916 if(s==left)
14917 {
14918 info = (walkflag(x-1,y+(bigHitbox?0:8),1,left)||walkflag(x-1,y+15,1,left));
14919 execute(info);
14920
14921 if(info.isUnwalkable())
14922 {
14923 shiftdir=-1;
14924 }
14925 else if(walkable)
14926 {
14927 info = walkflag(x-1,y+(bigHitbox?0:8)-1,1,left);
14928 execute(info);
14929 if(info.isUnwalkable())
14930 {
14931 shiftdir=-1;
14932 }
14933 }
14934 }
14935 else if(s==right)
14936 {
14937 info = walkflag(x+16,y+(bigHitbox?0:8),1,right)||walkflag(x+16,y+15,1,right);
14938 execute(info);
14939
14940 if(info.isUnwalkable())
14941 {
14942 shiftdir=-1;
14943 }
14944 else if(walkable)
14945 {
14946 info = walkflag(x+16,y+(bigHitbox?0:8)-1,1,right);
14947 execute(info);
14948
14949 if(info.isUnwalkable())
14950 {
14951 shiftdir=-1;
14952 }
14953 }
14954 }
14955 }
14956
14957 move(up);
14958 shiftdir=s;
14959
14960 if(!walkable)
14961 {
14962 if(shiftdir==-1) //Corner-shove; prevent being stuck on corners -V
14963 {
14964 if(!_walkflag(x, y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
14965 !_walkflag(x+8, y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
14966 _walkflag(x+15,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE))
14967 {
14968 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+15,y+(bigHitbox?0:8)-1))
14969 sprite::move((zfix)-1,(zfix)0);
14970 }
14971 else
14972 {
14973 if(_walkflag(x, y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
14974 !_walkflag(x+7, y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
14975 !_walkflag(x+15,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE))
14976 {
14977 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x,y+(bigHitbox?0:8)-1))
14978 sprite::move((zfix)1,(zfix)0);
14979 }
14980 else
14981 {
14982 pushing=push+1;
14983 }
14984 }
14985
14986 z3step=2;
14987 }
14988 else
14989 {
14990 pushing=push+1; // L: This makes solid damage combos and diagonal-triggered Armoses work.
14991 z3step=2;
14992 }
14993 }
14994
14995 return;
14996 }
14997 }
14998
14999 if(DrunkDown()&&(holddir==-1||holddir==down))
15000 {
15001 if(isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM) && !toogam)
15002 {
15003 }
15004 else
15005 {
15006 if(charging==0 && spins==0)
15007 {
15008 dir=down;
15009 }
15010
15011 holddir=down;
15012
15013 if(DrunkRight()&&shiftdir!=left)
15014 {
15015 shiftdir=right;
15016 }
15017 else if(DrunkLeft()&&shiftdir!=right)
15018 {
15019 shiftdir=left;
15020 }
15021 else
15022 {
15023 shiftdir=-1;
15024 }
15025
15026 //bool walkable;
15027 if(isSideViewHero() && !toogam && !getOnSideviewLadder() && action != sideswimming && action != sideswimhit && action != sideswimattacking)
15028 {
15029 walkable=false;
15030 }
15031 else
15032 {
15033 info = walkflag(x,y+15+z3step,2,down);
15034
15035 if(x.getInt()&7)
15036 info = info || walkflag(x+16,y+15+z3step,1,down);
15037 else
15038 info = info || walkflagMBlock(x+16, y+15+z3step);
15039
15040 execute(info);
15041
15042 if(info.isUnwalkable())
15043 {
15044 if(z3step==2)
15045 {
15046 z3step=1;
15047 info = walkflag(x,y+15+z3step,2,down);
15048
15049 if(x.getInt()&7)
15050 info = info || walkflag(x+16,y+15+z3step,1,down);
15051 else
15052 info = info || walkflagMBlock(x+16, y+15+z3step);
15053
15054 execute(info);
15055
15056 if(info.isUnwalkable())
15057 {
15058 walkable = false;
15059 }
15060 else
15061 {
15062 walkable=true;
15063 }
15064 }
15065 else
15066 {
15067 walkable=false;
15068 }
15069 }
15070 else
15071 {
15072 walkable = true;
15073 }
15074 }
15075
15076 int32_t s=shiftdir;
15077
15078 if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM))
15079 {
15080 shiftdir=-1;
15081 }
15082 else
15083 {
15084 if(s==left)
15085 {
15086 info = walkflag(x-1,y+(bigHitbox?0:8),1,left)||walkflag(x-1,y+15,1,left);
15087 execute(info);
15088
15089 if(info.isUnwalkable())
15090 {
15091 shiftdir=-1;
15092 }
15093 else if(walkable)
15094 {
15095 info = walkflag(x-1,y+16,1,left);
15096 execute(info);
15097
15098 if(info.isUnwalkable())
15099 {
15100 shiftdir=-1;
15101 }
15102 }
15103 }
15104 else if(s==right)
15105 {
15106 info = walkflag(x+16,y+(bigHitbox?0:8),1,right)||walkflag(x+16,y+15,1,right);
15107 execute(info);
15108
15109 if(info.isUnwalkable())
15110 {
15111 shiftdir=-1;
15112 }
15113 else if(walkable)
15114 {
15115 info = walkflag(x+16,y+16,1,right);
15116 execute(info);
15117
15118 if(info.isUnwalkable())
15119 {
15120 shiftdir=-1;
15121 }
15122 }
15123 }
15124 }
15125
15126 move(down);
15127 shiftdir=s;
15128
15129 if(!walkable)
15130 {
15131 if(shiftdir==-1) //Corner-shove; prevent being stuck on corners -V
15132 {
15133 if(!_walkflag(x, y+15+1,1,SWITCHBLOCK_STATE)&&
15134 !_walkflag(x+8, y+15+1,1,SWITCHBLOCK_STATE)&&
15135 _walkflag(x+15,y+15+1,1,SWITCHBLOCK_STATE))
15136 {
15137 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+15,y+15+1))
15138 sprite::move((zfix)-1,(zfix)0);
15139 }
15140 else if(_walkflag(x, y+15+1,1,SWITCHBLOCK_STATE)&&
15141 !_walkflag(x+7, y+15+1,1,SWITCHBLOCK_STATE)&&
15142 !_walkflag(x+15,y+15+1,1,SWITCHBLOCK_STATE))
15143 {
15144 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x,y+15+1))
15145 sprite::move((zfix)1,(zfix)0);
15146 }
15147 else //if(shiftdir==-1)
15148 {
15149 pushing=push+1;
15150
15151 if(action!=swimming)
15152 {
15153 }
15154 }
15155
15156 z3step=2;
15157 }
15158 else
15159 {
15160 pushing=push+1; // L: This makes solid damage combos and diagonal-triggered Armoses work.
15161
15162 if(action!=swimming)
15163 {
15164 }
15165
15166 z3step=2;
15167 }
15168 }
15169
15170 return;
15171 }
15172 }
15173
15174 if(DrunkLeft()&&(holddir==-1||holddir==left))
15175 {
15176 if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM) && !toogam)
15177 {
15178 }
15179 else
15180 {
15181 if(charging==0 && spins==0)
15182 {
15183 dir=left;
15184 }
15185
15186 holddir=left;
15187
15188 if(DrunkUp()&&shiftdir!=down)
15189 {
15190 shiftdir=up;
15191 }
15192 else if(DrunkDown()&&shiftdir!=up)
15193 {
15194 shiftdir=down;
15195 }
15196 else
15197 {
15198 shiftdir=-1;
15199 }
15200
15201 //bool walkable;
15202 info = walkflag(x-z3step,y+(bigHitbox?0:8),1,left)||walkflag(x-z3step,y+8,1,left);
15203
15204 if(y.getInt()&7)
15205 info = info || walkflag(x-z3step,y+16,1,left);
15206
15207 execute(info);
15208
15209 if(info.isUnwalkable())
15210 {
15211 if(z3step==2)
15212 {
15213 z3step=1;
15214 info = walkflag(x-z3step,y+(bigHitbox?0:8),1,left)||walkflag(x-z3step,y+8,1,left);
15215
15216 if(y.getInt()&7)
15217 info = info || walkflag(x-z3step,y+16,1,left);
15218
15219 execute(info);
15220
15221 if(info.isUnwalkable())
15222 {
15223 walkable = false;
15224 }
15225 else
15226 {
15227 walkable=true;
15228 }
15229 }
15230 else
15231 {
15232 walkable=false;
15233 }
15234 }
15235 else
15236 {
15237 walkable = true;
15238 }
15239
15240 int32_t s=shiftdir;
15241
15242 if((isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM)) || (isSideViewHero() && !getOnSideviewLadder() && action != sideswimming && action != sideswimhit && action != sideswimattacking))
15243 {
15244 shiftdir=-1;
15245 }
15246 else
15247 {
15248 if(s==up)
15249 {
15250 info = walkflag(x,y+(bigHitbox?0:8)-1,2,up)||walkflag(x+15,y+(bigHitbox?0:8)-1,1,up);
15251 execute(info);
15252
15253 if(info.isUnwalkable())
15254 {
15255 shiftdir=-1;
15256 }
15257 else if(walkable)
15258 {
15259 info = walkflag(x-1,y+(bigHitbox?0:8)-1,1,up);
15260 execute(info);
15261
15262 if(info.isUnwalkable())
15263 {
15264 shiftdir=-1;
15265 }
15266 }
15267 }
15268 else if(s==down)
15269 {
15270 info = walkflag(x,y+16,2,down)||walkflag(x+15,y+16,1,down);
15271 execute(info);
15272
15273 if(info.isUnwalkable())
15274 {
15275 shiftdir=-1;
15276 }
15277 else if(walkable)
15278 {
15279 info = walkflag(x-1,y+16,1,down);
15280 execute(info);
15281
15282 if(info.isUnwalkable())
15283 {
15284 shiftdir=-1;
15285 }
15286 }
15287 }
15288 }
15289
15290 move(left);
15291 shiftdir=s;
15292
15293 if(!walkable)
15294 {
15295 if(shiftdir==-1) //Corner-shove; prevent being stuck on corners -V
15296 {
15297 int32_t v1=bigHitbox?0:8;
15298 int32_t v2=bigHitbox?8:12;
15299
15300 if(!_walkflag(x-1,y+v1,1,SWITCHBLOCK_STATE)&&
15301 !_walkflag(x-1,y+v2,1,SWITCHBLOCK_STATE)&&
15302 _walkflag(x-1,y+15,1,SWITCHBLOCK_STATE))
15303 {
15304 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x-1,y+15))
15305 sprite::move((zfix)0,(zfix)-1);
15306 }
15307 else if(_walkflag(x-1,y+v1, 1,SWITCHBLOCK_STATE)&&
15308 !_walkflag(x-1,y+v2-1,1,SWITCHBLOCK_STATE)&&
15309 !_walkflag(x-1,y+15, 1,SWITCHBLOCK_STATE))
15310 {
15311 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x-1,y+v1))
15312 sprite::move((zfix)0,(zfix)1);
15313 }
15314 else //if(shiftdir==-1)
15315 {
15316 pushing=push+1;
15317
15318 if(action!=swimming)
15319 {
15320 }
15321 }
15322
15323 z3step=2;
15324 }
15325 else
15326 {
15327 pushing=push+1; // L: This makes solid damage combos and diagonal-triggered Armoses work.
15328
15329 if(action!=swimming)
15330 {
15331 }
15332
15333 z3step=2;
15334 }
15335 }
15336
15337 return;
15338 }
15339 }
15340
15341 if(DrunkRight()&&(holddir==-1||holddir==right))
15342 {
15343 if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM) && !toogam)
15344 {
15345 }
15346 else
15347 {
15348 if(charging==0 && spins==0)
15349 {
15350 dir=right;
15351 }
15352
15353 holddir=right;
15354
15355 if(DrunkUp()&&shiftdir!=down)
15356 {
15357 shiftdir=up;
15358 }
15359 else if(DrunkDown()&&shiftdir!=up)
15360 {
15361 shiftdir=down;
15362 }
15363 else
15364 {
15365 shiftdir=-1;
15366 }
15367
15368 //bool walkable;
15369 info = walkflag(x+15+z3step,y+(bigHitbox?0:8),1,right)||walkflag(x+15+z3step,y+8,1,right);
15370
15371 if(y.getInt()&7)
15372 info = info || walkflag(x+15+z3step,y+16,1,right);
15373
15374 execute(info);
15375
15376 if(info.isUnwalkable())
15377 {
15378 if(z3step==2)
15379 {
15380 z3step=1;
15381 info = walkflag(x+15+z3step,y+(bigHitbox?0:8),1,right)||walkflag(x+15+z3step,y+8,1,right);
15382
15383 if(y.getInt()&7)
15384 info = info || walkflag(x+15+z3step,y+16,1,right);
15385
15386 execute(info);
15387
15388 if(info.isUnwalkable())
15389 {
15390 walkable = false;
15391 }
15392 else
15393 {
15394 walkable=true;
15395 }
15396 }
15397 else
15398 {
15399 walkable=false;
15400 }
15401 }
15402 else
15403 {
15404 walkable = true;
15405 }
15406
15407 int32_t s=shiftdir;
15408
15409 if((isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM)) || (isSideViewHero() && !getOnSideviewLadder() && action != sideswimming && action != sideswimhit && action != sideswimattacking))
15410 {
15411 shiftdir=-1;
15412 }
15413 else
15414 {
15415 if(s==up)
15416 {
15417 info = walkflag(x,y+(bigHitbox?0:8)-1,2,up)||walkflag(x+15,y+(bigHitbox?0:8)-1,1,up);
15418 execute(info);
15419
15420 if(info.isUnwalkable())
15421 {
15422 shiftdir=-1;
15423 }
15424 else if(walkable)
15425 {
15426 info = walkflag(x+16,y+(bigHitbox?0:8)-1,1,up);
15427 execute(info);
15428
15429 if(info.isUnwalkable())
15430 {
15431 shiftdir=-1;
15432 }
15433 }
15434 }
15435 else if(s==down)
15436 {
15437 info = walkflag(x,y+16,2,down)||walkflag(x+15,y+16,1,down);
15438 execute(info);
15439
15440 if(info.isUnwalkable())
15441 {
15442 shiftdir=-1;
15443 }
15444 else if(walkable)
15445 {
15446 info = walkflag(x+16,y+16,1,down);
15447 execute(info);
15448
15449 if(info.isUnwalkable())
15450 {
15451 shiftdir=-1;
15452 }
15453 }
15454 }
15455 }
15456
15457 move(right);
15458 shiftdir=s;
15459
15460 if(!walkable)
15461 {
15462 if(shiftdir==-1) //Corner-shove; prevent being stuck on corners -V
15463 {
15464 int32_t v1=bigHitbox?0:8;
15465 int32_t v2=bigHitbox?8:12;
15466
15467 info = !walkflag(x+16,y+v1,1,right)&&
15468 !walkflag(x+16,y+v2,1,right)&&
15469 walkflag(x+16,y+15,1,right);
15470
15471 //do NOT execute these
15472 if(info.isUnwalkable())
15473 {
15474 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+16,y+15))
15475 sprite::move((zfix)0,(zfix)-1);
15476 }
15477 else
15478 {
15479 info = walkflag(x+16,y+v1, 1,right)&&
15480 !walkflag(x+16,y+v2-1,1,right)&&
15481 !walkflag(x+16,y+15, 1,right);
15482
15483 if(info.isUnwalkable())
15484 {
15485 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+16,y+v1))
15486 sprite::move((zfix)0,(zfix)1);
15487 }
15488 else //if(shiftdir==-1)
15489 {
15490 pushing=push+1;
15491 z3step=2;
15492
15493 if(action!=swimming)
15494 {
15495 }
15496 }
15497 }
15498
15499 z3step=2;
15500 }
15501 else
15502 {
15503 pushing=push+1; // L: This makes solid damage combos and diagonal-triggered Armoses work.
15504
15505 if(action!=swimming)
15506 {
15507 }
15508
15509 z3step=2;
15510 }
15511 }
15512
15513 return;
15514 }
15515 }
15516 }
15517 if(shield_forcedir > -1 && action != rafting)
15518 dir = shield_forcedir;
15519 int32_t wtry = iswaterex(MAPCOMBO(x,y+15), currmap, currscr, -1, x,y+15, true, false);
15520 int32_t wtry8 = iswaterex(MAPCOMBO(x+15,y+15), currmap, currscr, -1, x+15,y+15, true, false);
15521 int32_t wtrx = iswaterex(MAPCOMBO(x,y+(bigHitbox?0:8)), currmap, currscr, -1, x,y+(bigHitbox?0:8), true, false);
15522 int32_t wtrx8 = iswaterex(MAPCOMBO(x+15,y+(bigHitbox?0:8)), currmap, currscr, -1, x+15,y+(bigHitbox?0:8), true, false);
15523 int32_t wtrc = iswaterex(MAPCOMBO(x+8,y+(bigHitbox?8:12)), currmap, currscr, -1, x+8,y+(bigHitbox?8:12), true, false);
15524
15525 if(can_use_item(itype_flippers,i_flippers)&&current_item(itype_flippers) >= combobuf[wtrc].attribytes[0]&&(!(combobuf[wtrc].usrflags&cflag1) || (itemsbuf[current_item_id(itype_flippers)].flags & ITEM_FLAG3))&&!(ladderx+laddery)&&z==0&&fakez==0)
15526 {
15527 if(wtrx&&wtrx8&&wtry&&wtry8 && !DRIEDLAKE)
15528 {
15529 //action=swimming;
15530 if(action !=none && action != swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking && !isSideViewHero())
15531 {
15532 hopclk = 0xFF;
15533 }
15534 }
15535 }
15536
15537 return;
15538 } //endif (LTTPWALK)
15539 478 temp_step = hero_newstep;
15540 478 temp_x = x;
15541 478 temp_y = y;
15542
15543
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
478 if(isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM) && !toogam)
15544 {
15545 if(get_bit(quest_rules, qr_NEW_HERO_MOVEMENT) || IsSideSwim())
15546 goto LEFTRIGHT_NEWMOVE;
15547 else goto LEFTRIGHT_OLDMOVE;
15548 }
15549
15550 // make it easier to get in left & right doors
15551
15552 //ignore ladder for this part. sigh sigh sigh -DD
15553 478 oldladderx = ladderx;
15554 478 oldladdery = laddery;
15555
2/4
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 478 times.
478 if(get_bit(quest_rules, qr_NEW_HERO_MOVEMENT) || IsSideSwim())
15556 {
15557 if(isdungeon() && DrunkLeft() && (temp_x==32 && temp_y==80))
15558 {
15559 do
15560 {
15561 info = walkflag(temp_x,temp_y+(bigHitbox?0:8),1,left) ||
15562 walkflag(temp_x-temp_step,temp_y+(bigHitbox?0:8),1,left);
15563
15564 if(info.isUnwalkable())
15565 {
15566 if(temp_x != int32_t(temp_x))
15567 {
15568 temp_x = floor((double)temp_x);
15569 }
15570 else if(temp_step > 1)
15571 {
15572 if(temp_step != int32_t(temp_step)) //floor
15573 temp_step = floor((double)temp_step);
15574 else --temp_step;
15575 }
15576 else
15577 break;
15578 }
15579 }
15580 while(info.isUnwalkable());
15581
15582 if(!info.isUnwalkable())
15583 {
15584 x = temp_x;
15585 y = temp_y;
15586 hero_newstep = temp_step;
15587 //ONLY process the side-effects of the above walkflag if Hero will actually move
15588 //sigh sigh sigh... walkflag is a horrible mess :-/ -DD
15589 execute(info);
15590 move(left);
15591 return;
15592 }
15593 temp_x = x;
15594 temp_y = y;
15595 temp_step = hero_newstep;
15596 }
15597
15598 if(isdungeon() && DrunkRight() && temp_x==208 && temp_y==80)
15599 {
15600 do
15601 {
15602 info = walkflag(temp_x+15+temp_step,temp_y+(bigHitbox?0:8),1,right) ||
15603 walkflag(temp_x+15+temp_step,temp_y+8,1,right);
15604
15605 if(info.isUnwalkable())
15606 {
15607 if(temp_x != int32_t(temp_x))
15608 {
15609 temp_x = floor((double)temp_x);
15610 }
15611 else if(temp_step > 1)
15612 {
15613 if(temp_step != int32_t(temp_step)) //floor
15614 temp_step = floor((double)temp_step);
15615 else --temp_step;
15616 }
15617 else
15618 break;
15619 }
15620 }
15621 while(info.isUnwalkable());
15622
15623 if(!info.isUnwalkable())
15624 {
15625 x = temp_x;
15626 y = temp_y;
15627 hero_newstep = temp_step;
15628 execute(info);
15629 move(right);
15630 return;
15631 }
15632 temp_x = x;
15633 temp_y = y;
15634 temp_step = hero_newstep;
15635 }
15636
15637 ladderx = oldladderx;
15638 laddery = oldladdery;
15639
15640 if(DrunkUp())
15641 {
15642 if(xoff && !is_on_conveyor && action != swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking && jumping<1)
15643 {
15644 if(dir!=up && dir!=down)
15645 {
15646 if(xoff>2&&xoff<6)
15647 {
15648 move(dir);
15649 }
15650 else if(xoff>=6)
15651 {
15652 move(right);
15653 }
15654 else if(xoff>=1)
15655 {
15656 move(left);
15657 }
15658 }
15659 else
15660 {
15661 if(xoff>=4)
15662 {
15663 move(right);
15664 }
15665 else if(xoff<4)
15666 {
15667 move(left);
15668 }
15669 }
15670 }
15671 else
15672 {
15673 do
15674 {
15675 if(action==swimming || IsSideSwim() || action == swimhit)
15676 {
15677 info = walkflag(temp_x,temp_y+(bigHitbox?0:8)-temp_step,2,up);
15678
15679 if(_walkflag(temp_x+15, temp_y+(bigHitbox?0:8)-temp_step, 1,SWITCHBLOCK_STATE) &&
15680 !(iswaterex(MAPCOMBO(temp_x, temp_y+(bigHitbox?0:8)-temp_step), currmap, currscr, -1, temp_x, temp_y+(bigHitbox?0:8)-temp_step, true, false) &&
15681 iswaterex(MAPCOMBO(temp_x+15, temp_y+(bigHitbox?0:8)-temp_step), currmap, currscr, -1, temp_x+15, temp_y+(bigHitbox?0:8)-temp_step, true, false)))
15682 info.setUnwalkable(true);
15683 }
15684 else
15685 {
15686 info = walkflag(temp_x,temp_y+(bigHitbox?0:8)-temp_step,2,up);
15687 if(x.getInt() & 7)
15688 info = info || walkflag(temp_x+16,temp_y+(bigHitbox?0:8)-temp_step,1,up);
15689 else
15690 info = info || walkflagMBlock(temp_x+8,temp_y+(bigHitbox?0:8)-temp_step);
15691 }
15692
15693 if(info.isUnwalkable())
15694 {
15695 if(temp_y != int32_t(temp_y))
15696 {
15697 temp_y = floor((double)temp_y);
15698 }
15699 else if(temp_step > 1)
15700 {
15701 if(temp_step != int32_t(temp_step)) //floor
15702 temp_step = floor((double)temp_step);
15703 else --temp_step;
15704 }
15705 else
15706 break;
15707 }
15708 }
15709 while(info.isUnwalkable());
15710
15711 execute(info);
15712
15713 if(!info.isUnwalkable())
15714 {
15715 x = temp_x;
15716 y = temp_y;
15717 hero_newstep = temp_step;
15718 move(up);
15719 return;
15720 }
15721
15722 if(!DrunkLeft() && !DrunkRight())
15723 {
15724 if(NO_GRIDLOCK)
15725 {
15726 x = x.getInt();
15727 y = y.getInt();
15728 if(!_walkflag(x,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
15729 !_walkflag(x+8, y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
15730 _walkflag(x+15,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE))
15731 {
15732 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+15,y+(bigHitbox?0:8)-1))
15733 sprite::move((zfix)-1,(zfix)0);
15734 }
15735 else if(_walkflag(x,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
15736 !_walkflag(x+7, y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
15737 !_walkflag(x+15,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE))
15738 {
15739 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x,y+(bigHitbox?0:8)-1))
15740 sprite::move((zfix)1,(zfix)0);
15741 }
15742 else
15743 {
15744 pushing=push+1;
15745 }
15746 }
15747 else pushing=push+1;
15748
15749 if(charging==0 && spins==0)
15750 {
15751 dir=up;
15752 }
15753
15754 if(action!=swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking)
15755 {
15756 herostep();
15757 }
15758
15759 return;
15760 }
15761 else
15762 {
15763 goto LEFTRIGHT_NEWMOVE;
15764 }
15765 }
15766
15767 return;
15768 }
15769
15770 if(DrunkDown())
15771 {
15772 if(xoff && !is_on_conveyor && action != swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking && jumping<1)
15773 {
15774 if(dir!=up && dir!=down)
15775 {
15776 if(xoff>2&&xoff<6)
15777 {
15778 move(dir);
15779 }
15780 else if(xoff>=6)
15781 {
15782 move(right);
15783 }
15784 else if(xoff>=1)
15785 {
15786 move(left);
15787 }
15788 }
15789 else
15790 {
15791 if(xoff>=4)
15792 {
15793 move(right);
15794 }
15795 else if(xoff<4)
15796 {
15797 move(left);
15798 }
15799 }
15800 }
15801 else
15802 {
15803 do
15804 {
15805 if(action==swimming || IsSideSwim() || action == swimhit)
15806 {
15807 info=walkflag(temp_x,temp_y+15+temp_step,2,down);
15808
15809 if(_walkflag(temp_x+15, temp_y+15+temp_step, 1,SWITCHBLOCK_STATE) &&
15810 !(iswaterex(MAPCOMBO(temp_x, temp_y+15+temp_step), currmap, currscr, -1, temp_x, temp_y+15+temp_step, true, false) &&
15811 iswaterex(MAPCOMBO(temp_x+15, temp_y+15+temp_step), currmap, currscr, -1, temp_x+15, temp_y+15+temp_step, true, false)))
15812 info.setUnwalkable(true);
15813 }
15814 else
15815 {
15816 info=walkflag(temp_x,temp_y+15+temp_step,2,down);
15817 if(x.getInt() & 7)
15818 info = info || walkflag(temp_x+16,temp_y+15+temp_step,1,down);
15819 else
15820 info = info || walkflagMBlock(temp_x+8,temp_y+15+temp_step);
15821 }
15822
15823 if(info.isUnwalkable())
15824 {
15825 if(temp_y != int32_t(temp_y))
15826 {
15827 temp_y = floor((double)temp_y);
15828 }
15829 else if(temp_step > 1)
15830 {
15831 if(temp_step != int32_t(temp_step)) //floor
15832 temp_step = floor((double)temp_step);
15833 else --temp_step;
15834 }
15835 else
15836 break;
15837 }
15838 }
15839 while(info.isUnwalkable());
15840
15841 execute(info);
15842
15843 if(!info.isUnwalkable())
15844 {
15845 x = temp_x;
15846 y = temp_y;
15847 hero_newstep = temp_step;
15848 move(down);
15849 return;
15850 }
15851
15852 if(!DrunkLeft() && !DrunkRight())
15853 {
15854 if(NO_GRIDLOCK)
15855 {
15856 x = x.getInt();
15857 y = y.getInt();
15858 if(!_walkflag(x, y+15+1,1,SWITCHBLOCK_STATE)&&
15859 !_walkflag(x+8, y+15+1,1,SWITCHBLOCK_STATE)&&
15860 _walkflag(x+15,y+15+1,1,SWITCHBLOCK_STATE))
15861 {
15862 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+15,y+15+1))
15863 sprite::move((zfix)-1,(zfix)0);
15864 }
15865 else if(_walkflag(x, y+15+1,1,SWITCHBLOCK_STATE)&&
15866 !_walkflag(x+7, y+15+1,1,SWITCHBLOCK_STATE)&&
15867 !_walkflag(x+15,y+15+1,1,SWITCHBLOCK_STATE))
15868 {
15869 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x,y+15+1))
15870 sprite::move((zfix)1,(zfix)0);
15871 }
15872 else
15873 {
15874 pushing=push+1;
15875 }
15876 }
15877 else pushing=push+1;
15878
15879 if(charging==0 && spins==0)
15880 {
15881 dir=down;
15882 }
15883
15884 if(action!=swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking)
15885 {
15886 herostep();
15887 }
15888
15889 return;
15890 }
15891 else goto LEFTRIGHT_NEWMOVE;
15892 }
15893
15894 return;
15895 }
15896
15897 LEFTRIGHT_NEWMOVE:
15898 temp_x = x;
15899 temp_y = y;
15900 temp_step = hero_newstep;
15901 if(isdungeon() && (temp_y<=26 || temp_y>=134) && !get_bit(quest_rules,qr_FREEFORM) && !toogam)
15902 {
15903 return;
15904 }
15905
15906 if(DrunkLeft())
15907 {
15908 if(yoff && !is_on_conveyor && action != swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking && jumping<1)
15909 {
15910 if(dir!=left && dir!=right)
15911 {
15912 if(yoff>2&&yoff<6)
15913 {
15914 move(dir);
15915 }
15916 else if(yoff>=6)
15917 {
15918 move(down);
15919 }
15920 else if(yoff>=1)
15921 {
15922 move(up);
15923 }
15924 }
15925 else
15926 {
15927 if(yoff>=4)
15928 {
15929 move(down);
15930 }
15931 else if(yoff<4)
15932 {
15933 move(up);
15934 }
15935 }
15936 }
15937 else
15938 {
15939 do
15940 {
15941 info = walkflag(temp_x-temp_step,temp_y+(bigHitbox?0:8),1,left) ||
15942 walkflag(temp_x-temp_step,temp_y+(isSideViewHero() ?0:8), 1,left);
15943
15944 if(y.getInt() & 7)
15945 info = info || walkflag(temp_x-temp_step,temp_y+16,1,left);
15946
15947 if(info.isUnwalkable())
15948 {
15949 if(temp_x != int32_t(temp_x))
15950 {
15951 temp_x = floor((double)temp_x);
15952 }
15953 else if(temp_step > 1)
15954 {
15955 if(temp_step != int32_t(temp_step)) //floor
15956 temp_step = floor((double)temp_step);
15957 else --temp_step;
15958 }
15959 else
15960 break;
15961 }
15962 }
15963 while(info.isUnwalkable());
15964
15965 execute(info);
15966
15967 if(!info.isUnwalkable())
15968 {
15969 x = temp_x;
15970 y = temp_y;
15971 hero_newstep = temp_step;
15972 move(left);
15973 return;
15974 }
15975
15976 if(!DrunkUp() && !DrunkDown())
15977 {
15978 if(NO_GRIDLOCK)
15979 {
15980 x = x.getInt();
15981 y = y.getInt();
15982 int32_t v1=bigHitbox?0:8;
15983 int32_t v2=bigHitbox?8:12;
15984
15985 if(!_walkflag(x-1,y+v1,1,SWITCHBLOCK_STATE)&&
15986 !_walkflag(x-1,y+v2,1,SWITCHBLOCK_STATE)&&
15987 _walkflag(x-1,y+15,1,SWITCHBLOCK_STATE))
15988 {
15989 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x-1,y+15))
15990 sprite::move((zfix)0,(zfix)-1);
15991 }
15992 else if(_walkflag(x-1,y+v1,1,SWITCHBLOCK_STATE)&&
15993 !_walkflag(x-1,y+v2-1,1,SWITCHBLOCK_STATE)&&
15994 !_walkflag(x-1,y+15, 1,SWITCHBLOCK_STATE))
15995 {
15996 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x-1,y+v1))
15997 sprite::move((zfix)0,(zfix)1);
15998 }
15999 else
16000 {
16001 pushing=push+1;
16002 }
16003 }
16004 else pushing=push+1;
16005
16006 if(charging==0 && spins==0)
16007 {
16008 dir=left;
16009 }
16010
16011 if(action!=swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking)
16012 {
16013 herostep();
16014 }
16015
16016 return;
16017 }
16018 }
16019
16020 return;
16021 }
16022
16023 if(DrunkRight())
16024 {
16025 if(yoff && !is_on_conveyor && action != swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking && jumping<1)
16026 {
16027 if(dir!=left && dir!=right)
16028 {
16029 if(yoff>2&&yoff<6)
16030 {
16031 move(dir);
16032 }
16033 else if(yoff>=6)
16034 {
16035 move(down);
16036 }
16037 else if(yoff>=1)
16038 {
16039 move(up);
16040 }
16041 }
16042 else
16043 {
16044 if(yoff>=4)
16045 {
16046 move(down);
16047 }
16048 else if(yoff<4)
16049 {
16050 move(up);
16051 }
16052 }
16053 }
16054 else
16055 {
16056 do
16057 {
16058 info = walkflag(temp_x+15+temp_step,temp_y+(bigHitbox?0:8),1,right) ||
16059 walkflag(temp_x+15+temp_step,temp_y+(isSideViewHero() ?0:8),1,right);
16060
16061 if(y.getInt() & 7)
16062 info = info || walkflag(temp_x+15+temp_step,y+16,1,right);
16063
16064 if(info.isUnwalkable())
16065 {
16066 if(temp_x != int32_t(temp_x))
16067 {
16068 temp_x = floor((double)temp_x);
16069 }
16070 else if(temp_step > 1)
16071 {
16072 if(temp_step != int32_t(temp_step)) //floor
16073 temp_step = floor((double)temp_step);
16074 else --temp_step;
16075 }
16076 else
16077 break;
16078 }
16079 }
16080 while(info.isUnwalkable());
16081
16082 execute(info);
16083
16084 if(!info.isUnwalkable())
16085 {
16086 x = temp_x;
16087 y = temp_y;
16088 hero_newstep = temp_step;
16089 move(right);
16090 return;
16091 }
16092
16093 if(!DrunkUp() && !DrunkDown())
16094 {
16095 if(NO_GRIDLOCK)
16096 {
16097 x = x.getInt();
16098 y = y.getInt();
16099 int32_t v1=bigHitbox?0:8;
16100 int32_t v2=bigHitbox?8:12;
16101
16102 if(!_walkflag(x+16,y+v1,1,SWITCHBLOCK_STATE)&&
16103 !_walkflag(x+16,y+v2,1,SWITCHBLOCK_STATE)&&
16104 _walkflag(x+16,y+15,1,SWITCHBLOCK_STATE))
16105 {
16106 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+16,y+15))
16107 sprite::move((zfix)0,(zfix)-1);
16108 }
16109 else if(_walkflag(x+16,y+v1,1,SWITCHBLOCK_STATE)&&
16110 !_walkflag(x+16,y+v2-1,1,SWITCHBLOCK_STATE)&&
16111 !_walkflag(x+16,y+15,1,SWITCHBLOCK_STATE))
16112 {
16113 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+16,y+v1))
16114 sprite::move((zfix)0,(zfix)1);
16115 }
16116 else
16117 {
16118 pushing=push+1;
16119 }
16120 }
16121 else pushing=push+1;
16122
16123 if(charging==0 && spins==0)
16124 {
16125 dir=right;
16126 }
16127
16128 if(action!=swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking)
16129 {
16130 herostep();
16131 }
16132
16133 return;
16134 }
16135 }
16136 }
16137 }
16138 else
16139 {
16140 956 info = walkflag(x-int32_t(lsteps[x.getInt()&7]),y+(bigHitbox?0:8),1,left) ||
16141 478 walkflag(x-int32_t(lsteps[x.getInt()&7]),y+8,1,left);
16142
16143
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
478 if(isdungeon() && DrunkLeft() && !info.isUnwalkable() && (x==32 && y==80))
16144 {
16145 //ONLY process the side-effects of the above walkflag if Hero will actually move
16146 //sigh sigh sigh... walkflag is a horrible mess :-/ -DD
16147 execute(info);
16148 move(left);
16149 return;
16150 }
16151
16152 956 info = walkflag(x+15+int32_t(lsteps[x.getInt()&7]),y+(bigHitbox?0:8),1,right) ||
16153 478 walkflag(x+15+int32_t(lsteps[x.getInt()&7]),y+8,1,right);
16154
16155
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
478 if(isdungeon() && DrunkRight() && !info.isUnwalkable() && x==208 && y==80)
16156 {
16157 execute(info);
16158 move(right);
16159 return;
16160 }
16161
16162 478 ladderx = oldladderx;
16163 478 laddery = oldladdery;
16164
16165
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 403 times.
478 if(DrunkUp())
16166 {
16167
8/14
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 73 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
75 if(xoff && !is_on_conveyor && action != swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking && jumping<1)
16168 {
16169
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if(dir!=up && dir!=down)
16170 {
16171
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
2 if(xoff>2&&xoff<6)
16172 {
16173 1 move(dir);
16174 1 }
16175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if(xoff>=6)
16176 {
16177 move(right);
16178 }
16179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if(xoff>=1)
16180 {
16181 1 move(left);
16182 1 }
16183 2 }
16184 else
16185 {
16186 if(xoff>=4)
16187 {
16188 move(right);
16189 }
16190 else if(xoff<4)
16191 {
16192 move(left);
16193 }
16194 }
16195 2 }
16196 else
16197 {
16198
3/6
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
73 if(action==swimming || IsSideSwim() || action == swimhit)
16199 {
16200 info = walkflag(x,y+(bigHitbox?0:8)-int32_t(lsteps[y.getInt()&7]),2,up);
16201
16202 if(_walkflag(x+15, y+(bigHitbox?0:8)-int32_t(lsteps[y.getInt()&7]), 1,SWITCHBLOCK_STATE) &&
16203 !(iswaterex(MAPCOMBO(x, y+(bigHitbox?0:8)-int32_t(lsteps[y.getInt()&7])), currmap, currscr, -1, x, y+(bigHitbox?0:8)-int32_t(lsteps[y.getInt()&7])) &&
16204 iswaterex(MAPCOMBO(x+15, y+(bigHitbox?0:8)-int32_t(lsteps[y.getInt()&7])), currmap, currscr, -1, x+15, y+(bigHitbox?0:8)-int32_t(lsteps[y.getInt()&7]))))
16205 info.setUnwalkable(true);
16206 }
16207 else
16208 {
16209 73 info = walkflag(x,y+(bigHitbox?0:8)-int32_t(lsteps[y.getInt()&7]),2,up);
16210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if(x.getInt() & 7)
16211 info = info || walkflag(x+16,y+(bigHitbox?0:8)-int32_t(lsteps[y.getInt()&7]),1,up);
16212 else
16213 73 info = info || walkflagMBlock(x+8,y+(bigHitbox?0:8)-int32_t(lsteps[y.getInt()&7]));
16214 }
16215
16216 73 execute(info);
16217
16218
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 45 times.
73 if(!info.isUnwalkable())
16219 {
16220 45 move(up);
16221 45 return;
16222 }
16223
16224
3/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 26 times.
28 if(!DrunkLeft() && !DrunkRight())
16225 {
16226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if(NO_GRIDLOCK)
16227 {
16228 if(!_walkflag(x,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
16229 !_walkflag(x+8, y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
16230 _walkflag(x+15,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE))
16231 {
16232 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+15,y+(bigHitbox?0:8)-1))
16233 sprite::move((zfix)-1,(zfix)0);
16234 }
16235 else if(_walkflag(x,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
16236 !_walkflag(x+7, y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
16237 !_walkflag(x+15,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE))
16238 {
16239 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x,y+(bigHitbox?0:8)-1))
16240 sprite::move((zfix)1,(zfix)0);
16241 }
16242 else
16243 {
16244 pushing=push+1;
16245 }
16246 }
16247 26 else pushing=push+1;
16248
16249
2/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
26 if(charging==0 && spins==0)
16250 {
16251 26 dir=up;
16252 26 }
16253
16254
4/8
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 26 times.
26 if(action!=swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking)
16255 {
16256 26 herostep();
16257 26 }
16258
16259 26 return;
16260 }
16261 else
16262 {
16263 2 goto LEFTRIGHT_OLDMOVE;
16264 }
16265 }
16266
16267 2 return;
16268 }
16269
16270
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 373 times.
403 if(DrunkDown())
16271 {
16272
1/14
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
30 if(xoff && !is_on_conveyor && action != swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking && jumping<1)
16273 {
16274 if(dir!=up && dir!=down)
16275 {
16276 if(xoff>2&&xoff<6)
16277 {
16278 move(dir);
16279 }
16280 else if(xoff>=6)
16281 {
16282 move(right);
16283 }
16284 else if(xoff>=1)
16285 {
16286 move(left);
16287 }
16288 }
16289 else
16290 {
16291 if(xoff>=4)
16292 {
16293 move(right);
16294 }
16295 else if(xoff<4)
16296 {
16297 move(left);
16298 }
16299 }
16300 }
16301 else
16302 {
16303
3/6
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 30 times.
30 if(action==swimming || IsSideSwim() || action == swimhit)
16304 {
16305 info=walkflag(x,y+15+int32_t(lsteps[y.getInt()&7]),2,down);
16306
16307 if(_walkflag(x+15, y+15+int32_t(lsteps[y.getInt()&7]), 1,SWITCHBLOCK_STATE) &&
16308 !(iswaterex(MAPCOMBO(x, y+15+int32_t(lsteps[y.getInt()&7])), currmap, currscr, -1, x, y+15+int32_t(lsteps[y.getInt()&7])) &&
16309 iswaterex(MAPCOMBO(x+15, y+15+int32_t(lsteps[y.getInt()&7])), currmap, currscr, -1, x+15, y+15+int32_t(lsteps[y.getInt()&7]))))
16310 info.setUnwalkable(true);
16311 }
16312 else
16313 {
16314 30 info=walkflag(x,y+15+int32_t(lsteps[y.getInt()&7]),2,down);
16315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if(x.getInt() & 7)
16316 info = (info || walkflag(x+16,y+15+int32_t(lsteps[y.getInt()&7]),1,down));
16317 else
16318 30 info = (info || walkflagMBlock(x+8,y+15+int32_t(lsteps[y.getInt()&7])));
16319 }
16320
16321 30 execute(info);
16322
16323
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 25 times.
30 if(!info.isUnwalkable())
16324 {
16325 25 move(down);
16326 25 return;
16327 }
16328
16329
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if(!DrunkLeft() && !DrunkRight())
16330 {
16331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(NO_GRIDLOCK)
16332 {
16333 if(!_walkflag(x, y+15+1,1,SWITCHBLOCK_STATE)&&
16334 !_walkflag(x+8, y+15+1,1,SWITCHBLOCK_STATE)&&
16335 _walkflag(x+15,y+15+1,1,SWITCHBLOCK_STATE))
16336 {
16337 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+15,y+15+1))
16338 sprite::move((zfix)-1,(zfix)0);
16339 }
16340 else if(_walkflag(x, y+15+1,1,SWITCHBLOCK_STATE)&&
16341 !_walkflag(x+7, y+15+1,1,SWITCHBLOCK_STATE)&&
16342 !_walkflag(x+15,y+15+1,1,SWITCHBLOCK_STATE))
16343 {
16344 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x,y+15+1))
16345 sprite::move((zfix)1,(zfix)0);
16346 }
16347 else
16348 {
16349 pushing=push+1;
16350 }
16351 }
16352 5 else pushing=push+1;
16353
16354
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 if(charging==0 && spins==0)
16355 {
16356 5 dir=down;
16357 5 }
16358
16359
4/8
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
5 if(action!=swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking)
16360 {
16361 5 herostep();
16362 5 }
16363
16364 5 return;
16365 }
16366 else goto LEFTRIGHT_OLDMOVE;
16367 }
16368
16369 return;
16370 }
16371
16372 LEFTRIGHT_OLDMOVE:
16373
16374
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 375 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
375 if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM) && !toogam)
16375 {
16376 return;
16377 }
16378
16379
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 313 times.
375 if(DrunkLeft())
16380 {
16381
1/14
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
62 if(yoff && !is_on_conveyor && action != swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking && jumping<1)
16382 {
16383 if(dir!=left && dir!=right)
16384 {
16385 if(yoff>2&&yoff<6)
16386 {
16387 move(dir);
16388 }
16389 else if(yoff>=6)
16390 {
16391 move(down);
16392 }
16393 else if(yoff>=1)
16394 {
16395 move(up);
16396 }
16397 }
16398 else
16399 {
16400 if(yoff>=4)
16401 {
16402 move(down);
16403 }
16404 else if(yoff<4)
16405 {
16406 move(up);
16407 }
16408 }
16409 }
16410 else
16411 {
16412 124 info = walkflag(x-int32_t(lsteps[x.getInt()&7]),y+(bigHitbox?0:8),1,left) ||
16413 62 walkflag(x-int32_t(lsteps[x.getInt()&7]),y+(isSideViewHero() ?0:8), 1,left);
16414
16415 62 execute(info);
16416
16417
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 47 times.
62 if(!info.isUnwalkable())
16418 {
16419 47 move(left);
16420 47 return;
16421 }
16422
16423
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if(!DrunkUp() && !DrunkDown())
16424 {
16425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if(NO_GRIDLOCK)
16426 {
16427 int32_t v1=bigHitbox?0:8;
16428 int32_t v2=bigHitbox?8:12;
16429
16430 if(!_walkflag(x-1,y+v1,1,SWITCHBLOCK_STATE)&&
16431 !_walkflag(x-1,y+v2,1,SWITCHBLOCK_STATE)&&
16432 _walkflag(x-1,y+15,1,SWITCHBLOCK_STATE))
16433 {
16434 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x-1,y+15))
16435 sprite::move((zfix)0,(zfix)-1);
16436 }
16437 else if(_walkflag(x-1,y+v1, 1,SWITCHBLOCK_STATE)&&
16438 !_walkflag(x-1,y+v2-1,1,SWITCHBLOCK_STATE)&&
16439 !_walkflag(x-1,y+15, 1,SWITCHBLOCK_STATE))
16440 {
16441 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x-1,y+v1))
16442 sprite::move((zfix)0,(zfix)1);
16443 }
16444 else
16445 {
16446 pushing=push+1;
16447 }
16448 }
16449 15 else pushing=push+1;
16450
16451
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if(charging==0 && spins==0)
16452 {
16453 15 dir=left;
16454 15 }
16455
16456
4/8
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
15 if(action!=swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking)
16457 {
16458 15 herostep();
16459 15 }
16460
16461 15 return;
16462 }
16463 }
16464
16465 return;
16466 }
16467
16468
2/2
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 69 times.
313 if(DrunkRight())
16469 {
16470
1/14
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
69 if(yoff && !is_on_conveyor && action != swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking && jumping<1)
16471 {
16472 if(dir!=left && dir!=right)
16473 {
16474 if(yoff>2&&yoff<6)
16475 {
16476 move(dir);
16477 }
16478 else if(yoff>=6)
16479 {
16480 move(down);
16481 }
16482 else if(yoff>=1)
16483 {
16484 move(up);
16485 }
16486 }
16487 else
16488 {
16489 if(yoff>=4)
16490 {
16491 move(down);
16492 }
16493 else if(yoff<4)
16494 {
16495 move(up);
16496 }
16497 }
16498 }
16499 else
16500 {
16501 138 info = walkflag(x+15+int32_t(lsteps[x.getInt()&7]),y+(bigHitbox?0:8),1,right)
16502 69 || walkflag(x+15+int32_t(lsteps[x.getInt()&7]),y+(isSideViewHero()?0:8),1,right);
16503
16504 69 execute(info);
16505
16506
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 65 times.
69 if(!info.isUnwalkable())
16507 {
16508 65 move(right);
16509 65 return;
16510 }
16511
16512
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if(!DrunkUp() && !DrunkDown())
16513 {
16514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(NO_GRIDLOCK)
16515 {
16516 int32_t v1=bigHitbox?0:8;
16517 int32_t v2=bigHitbox?8:12;
16518
16519 if(!_walkflag(x+16,y+v1,1,SWITCHBLOCK_STATE)&&
16520 !_walkflag(x+16,y+v2,1,SWITCHBLOCK_STATE)&&
16521 _walkflag(x+16,y+15,1,SWITCHBLOCK_STATE))
16522 {
16523 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+16,y+15))
16524 sprite::move((zfix)0,(zfix)-1);
16525 }
16526 else if(_walkflag(x+16,y+v1,1,SWITCHBLOCK_STATE)&&
16527 !_walkflag(x+16,y+v2-1,1,SWITCHBLOCK_STATE)&&
16528 !_walkflag(x+16,y+15,1,SWITCHBLOCK_STATE))
16529 {
16530 if(hclk || ((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+16,y+v1))
16531 sprite::move((zfix)0,(zfix)1);
16532 }
16533 else
16534 {
16535 pushing=push+1;
16536 }
16537 }
16538 4 else pushing=push+1;
16539
16540
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if(charging==0 && spins==0)
16541 {
16542 4 dir=right;
16543 4 }
16544
16545
4/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
4 if(action!=swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking)
16546 {
16547 4 herostep();
16548 4 }
16549
16550 4 return;
16551 }
16552 }
16553 }
16554 }
16555 1523 }
16556
16557 //solid ffc checking should probably be moved to here.
16558 989 void HeroClass::move(int32_t d2, int32_t forceRate)
16559 {
16560
3/6
✓ Branch 0 taken 989 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 989 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 989 times.
989 if( inlikelike || lstunclock > 0 || is_conveyor_stunned)
16561 return;
16562
16563
2/4
✓ Branch 0 taken 989 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 989 times.
989 if(!get_bit(quest_rules, qr_NEW_HERO_MOVEMENT) && !IsSideSwim())
16564 {
16565 989 moveOld(d2);
16566 989 return;
16567 }
16568
16569 bool slowcombo = (combo_class_buf[combobuf[MAPCOMBO(x+7,y+8)].type].slow_movement && _effectflag(x+7,y+8,1, -1) && ((z==0 && fakez==0) || tmpscr->flags2&fAIRCOMBOS)) ||
16570 (isSideViewHero() && (on_sideview_solid_oldpos(x,y,old_x,old_y)||getOnSideviewLadder()) && combo_class_buf[combobuf[MAPCOMBO(x+7,y+8)].type].slow_movement && _effectflag(x+7,y+8,1, -1));
16571 //!DIMITODO: add QR for slow combos under hero
16572 for (int32_t i = 0; i <= 1; ++i)
16573 {
16574 if(tmpscr2[i].valid!=0)
16575 {
16576 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
16577 {
16578 if (combobuf[MAPCOMBO2(i,x+7,y+8)].type == cBRIDGE && !_walkflag_layer(x+7,y+8,1, &(tmpscr2[i]))) slowcombo = false;
16579 }
16580 else
16581 {
16582 if (combobuf[MAPCOMBO2(i,x+7,y+8)].type == cBRIDGE && _effectflag_layer(x+7,y+8,1, &(tmpscr2[i]))) slowcombo = false;
16583 }
16584 }
16585 }
16586 bool slowcharging = charging>0 && (itemsbuf[getWpnPressed(itype_sword)].flags & ITEM_FLAG10);
16587 bool is_swimming = (action == swimming);
16588 bool fastSwim = (zinit.hero_swim_speed>60);
16589 zfix rate(steprate);
16590 int32_t shieldid = getCurrentActiveShield();
16591 if(shieldid > -1)
16592 {
16593 itemdata const& shield = itemsbuf[shieldid];
16594 if(shield.flags & ITEM_FLAG10) //Change Speed flag
16595 {
16596 zfix perc = shield.misc7;
16597 perc /= 100;
16598 if(perc < 0)
16599 perc = (perc*-1)+1;
16600 rate = (rate * perc) + shield.misc8;
16601 }
16602 }
16603
16604 zfix dx, dy;
16605 zfix movepix(rate / 100);
16606 zfix step(movepix);
16607 zfix step_diag(movepix);
16608 zfix up_step(game->get_sideswim_up() / -100.0);
16609 zfix left_step(game->get_sideswim_side() / -100.0);
16610 zfix right_step(game->get_sideswim_side() / 100.0);
16611 zfix down_step(game->get_sideswim_down() / 100.0);
16612 bool checkladder = false;
16613
16614 if(hero_newstep > movepix) hero_newstep = movepix;
16615 if(hero_newstep_diag > movepix) hero_newstep_diag = movepix;
16616 //2/3 speed
16617 if((is_swimming && fastSwim) || (!is_swimming && (slowcharging ^ slowcombo)))
16618 {
16619 step = ((step / 3.0) * 2);
16620 step_diag = ((step_diag / 3.0) * 2);
16621 up_step = ((up_step / 3.0) * 2);
16622 left_step = ((left_step / 3.0) * 2);
16623 right_step = ((right_step / 3.0) * 2);
16624 down_step = ((down_step / 3.0) * 2);
16625 }
16626 //1/2 speed
16627 else if((is_swimming && !fastSwim) || (slowcharging && slowcombo))
16628 {
16629 step /= 2;
16630 step_diag /= 2;
16631 up_step /= 2;
16632 left_step /= 2;
16633 right_step /= 2;
16634 down_step /= 2;
16635 }
16636 //normal speed
16637 else
16638 {
16639 //no modification
16640 }
16641
16642 if(diagonalMovement)
16643 {
16644 //zprint2("Player's X is %d, Y is %d\n", x, y);
16645 if(((d2 == up || d2 == down) && (shiftdir == left || shiftdir == right)) ||
16646 (d2 == left || d2 == right) && (shiftdir == up || shiftdir == down))
16647 {
16648 if(hero_newstep > 0 && hero_newstep_diag > 0)
16649 {
16650 step = STEP_DIAGONAL(step);
16651 step_diag = STEP_DIAGONAL(step_diag);
16652 up_step = STEP_DIAGONAL(up_step);
16653 left_step = STEP_DIAGONAL(left_step);
16654 right_step = STEP_DIAGONAL(right_step);
16655 down_step = STEP_DIAGONAL(down_step);
16656 }
16657 }
16658 if(hero_newstep < step) step = hero_newstep; //handle collision
16659 if(hero_newstep_diag < step_diag) step_diag = hero_newstep_diag; //handle collision
16660 switch(d2)
16661 {
16662 case up:
16663 switch(shiftdir)
16664 {
16665 case left:
16666 dx = -step_diag;
16667 if (IsSideSwim()) dx = left_step;
16668 break;
16669 case right:
16670 dx = step_diag;
16671 if (IsSideSwim()) dx = right_step;
16672 break;
16673 }
16674 if(walkable)
16675 {
16676 if (!IsSideSwim()) dy = -step;
16677 if (IsSideSwim())
16678 {
16679 dy = up_step;
16680 if (!iswaterex(MAPCOMBO(x,y+8-(bigHitbox*8)+floor(up_step)), currmap, currscr, -1, x, y+8-(bigHitbox*8)-2, true, false)) checkladder = true;
16681 }
16682 }
16683 break;
16684 case down:
16685 switch(shiftdir)
16686 {
16687 case left:
16688 dx = -step_diag;
16689 if (IsSideSwim()) dx = left_step;
16690 break;
16691 case right:
16692 dx = step_diag;
16693 if (IsSideSwim()) dx = right_step;
16694 break;
16695 }
16696 if(walkable)
16697 {
16698 dy = step;
16699 if (IsSideSwim()) dy = down_step;
16700 }
16701 break;
16702 case left:
16703 switch(shiftdir)
16704 {
16705 case up:
16706 if (!IsSideSwim()) dy = -step_diag;
16707 if (IsSideSwim())
16708 {
16709 dy = up_step;
16710 if (!iswaterex(MAPCOMBO(x,y+8-(bigHitbox*8)+floor(up_step)), currmap, currscr, -1, x, y+8-(bigHitbox*8)-2, true, false)) checkladder = true;
16711 }
16712 break;
16713 case down:
16714 dy = step_diag;
16715 if (IsSideSwim()) dy = down_step;
16716 break;
16717 }
16718 if(walkable)
16719 {
16720 dx = -step;
16721 if (IsSideSwim()) dx = left_step;
16722 }
16723 break;
16724 case right:
16725 switch(shiftdir)
16726 {
16727 case up:
16728 if (!IsSideSwim()) dy = -step_diag;
16729 if (IsSideSwim())
16730 {
16731 dy = up_step;
16732 if (!iswaterex(MAPCOMBO(x,y+8-(bigHitbox*8)+floor(up_step)), currmap, currscr, -1, x, y+8-(bigHitbox*8)-2, true, false)) checkladder = true;
16733 }
16734 break;
16735 case down:
16736 dy = step_diag;
16737 if (IsSideSwim()) dy = down_step;
16738 break;
16739 }
16740 if(walkable)
16741 {
16742 dx = step;
16743 if (IsSideSwim()) dx = right_step;
16744 }
16745 break;
16746 };
16747 }
16748 else
16749 {
16750 if(hero_newstep < step) step = hero_newstep; //handle collision
16751 switch(d2)
16752 {
16753 case up:
16754 dy -= step;
16755 if (IsSideSwim()) dy = up_step;
16756 break;
16757 case down:
16758 dy += step;
16759 if (IsSideSwim()) dy = down_step;
16760 break;
16761 case left:
16762 dx -= step;
16763 if (IsSideSwim()) dx = left_step;
16764 break;
16765 case right:
16766 dx += step;
16767 if (IsSideSwim()) dx = right_step;
16768 break;
16769 };
16770 }
16771 hero_newstep = movepix;
16772 hero_newstep_diag = movepix;
16773
16774 if((charging==0 || attack==wHammer) && spins==0 && attackclk!=HAMMERCHARGEFRAME && action != sideswimattacking && !(IsSideSwim() && get_bit(quest_rules,qr_SIDESWIMDIR) && (d2 == up || d2 == down))) //!DIRECTION SET
16775 {
16776 dir=d2;
16777 }
16778 else if (IsSideSwim() && get_bit(quest_rules,qr_SIDESWIMDIR) && (d2 == up || d2 == down) && (shiftdir == left || shiftdir == right) && (charging==0 && spins==0))
16779 {
16780 dir = shiftdir;
16781 }
16782 if(forceRate > -1)
16783 {
16784 checkladder = false;
16785 switch(dir)
16786 {
16787 case right:
16788 case r_up:
16789 case r_down:
16790 dx = zfix(forceRate) / 100;
16791 break;
16792 case left:
16793 case l_up:
16794 case l_down:
16795 dx = zfix(-forceRate) / 100;
16796 break;
16797 default:
16798 dx = 0;
16799 }
16800 switch(dir)
16801 {
16802 case down:
16803 case r_down:
16804 case l_down:
16805 dy = zfix(forceRate) / 100;
16806 break;
16807 case up:
16808 case r_up:
16809 case l_up:
16810 dy = zfix(-forceRate) / 100;
16811 break;
16812 default:
16813 dy = 0;
16814 }
16815 }
16816 if(dx == 0 && dy == 0) return;
16817 if(action != swimming && action != sideswimming && action != sideswimhit && action != sideswimattacking)
16818 {
16819 herostep();
16820
16821 //ack... don't walk if in midair! -DD
16822 if(charging==0 && spins==0 && z==0 && fakez==0 && !(isSideViewHero() && !on_sideview_solid_oldpos(x,y,old_x,old_y) && !getOnSideviewLadder()))
16823 {
16824 action=walking; FFCore.setHeroAction(walking);
16825 }
16826
16827 if(++hero_count > (16*hero_animation_speed))
16828 hero_count=0;
16829 }
16830 else if(!(frame & 1))
16831 {
16832 herostep();
16833 }
16834
16835 if(charging==0 || attack!=wHammer)
16836 {
16837 sprite::move(dx, dy);
16838 WalkflagInfo info;
16839 info = walkflag(x,y+8-(bigHitbox*8)-4,2,up);
16840 execute(info);
16841 if (checkladder && !canSideviewLadderRemote(x, y-4) && !info.isUnwalkable() && (y + 8 - (bigHitbox * 8) - 4) > 0)
16842 {
16843 if (game->get_sideswim_jump() != 0)
16844 {
16845 setFall(zfix(0-(FEATHERJUMP*(game->get_sideswim_jump()/10000.0))));
16846 sfx(WAV_ZN1SPLASH,(int32_t)x);
16847 hopclk = 0;
16848 if (charging || spins) action = attacking;
16849 else action = none;
16850 }
16851 else
16852 {
16853 sprite::move(zfix(0), zfix(-1*dy));
16854 }
16855 }
16856 }
16857 989 }
16858
16859 989 void HeroClass::moveOld(int32_t d2)
16860 {
16861 //al_trace("%s\n",d2==up?"up":d2==down?"down":d2==left?"left":d2==right?"right":"?");
16862 static bool totalskip = false;
16863
16864
3/6
✓ Branch 0 taken 989 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 989 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 989 times.
989 if( inlikelike || lstunclock > 0 || is_conveyor_stunned)
16865 return;
16866
16867 989 int32_t dx=0,dy=0;
16868 989 int32_t xstep=lsteps[x.getInt()&7];
16869 989 int32_t ystep=lsteps[y.getInt()&7];
16870 989 int32_t z3skip=0;
16871 989 int32_t z3diagskip=0;
16872
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 989 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1978 bool slowcombo = (combo_class_buf[combobuf[MAPCOMBO(x+7,y+8)].type].slow_movement && ((z==0 && fakez == 0) || tmpscr->flags2&fAIRCOMBOS)) ||
16873
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 989 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
989 (isSideViewHero() && (on_sideview_solid_oldpos(x,y,old_x,old_y)||getOnSideviewLadder()) && combo_class_buf[combobuf[MAPCOMBO(x+7,y+8)].type].slow_movement);
16874
1/2
✓ Branch 0 taken 989 times.
✗ Branch 1 not taken.
989 bool slowcharging = charging>0 && (itemsbuf[getWpnPressed(itype_sword)].flags & ITEM_FLAG10);
16875 989 bool is_swimming = (action == swimming);
16876
16877 //slow walk combo, or charging, moves at 2/3 speed
16878 if(
16879
2/4
✓ Branch 0 taken 989 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 989 times.
989 (!is_swimming && (slowcharging ^ slowcombo))||
16880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 989 times.
989 (is_swimming && (zinit.hero_swim_speed>60))
16881 )
16882 {
16883 totalskip = false;
16884
16885 if(diagonalMovement)
16886 {
16887 skipstep=(skipstep+1)%6;
16888
16889 if(skipstep%2==0) z3skip=1;
16890 else z3skip=0;
16891
16892 if(skipstep%3==0) z3diagskip=1;
16893 else z3diagskip=0;
16894 }
16895 else
16896 {
16897 if(d2<left)
16898 {
16899 if(ystep>1)
16900 {
16901 skipstep^=1;
16902 ystep=skipstep;
16903 }
16904 }
16905 else
16906 {
16907 if(xstep>1)
16908 {
16909 skipstep^=1;
16910 xstep=skipstep;
16911 }
16912 }
16913 }
16914 }
16915 // else if(is_swimming || (slowcharging && slowcombo))
16916 else if(
16917
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 989 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
989 (is_swimming && (zinit.hero_swim_speed<60))||
16918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 989 times.
989 (slowcharging && slowcombo)
16919 )
16920 {
16921 //swimming, or charging on a slow combo, moves at 1/2 speed
16922 totalskip = !totalskip;
16923
16924 if(diagonalMovement)
16925 {
16926 skipstep=0;
16927 }
16928 }
16929 else
16930 {
16931 989 totalskip = false;
16932
16933
1/2
✓ Branch 0 taken 989 times.
✗ Branch 1 not taken.
989 if(diagonalMovement)
16934 {
16935 skipstep=0;
16936 }
16937 }
16938
16939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 989 times.
989 if(!totalskip)
16940 {
16941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 989 times.
989 if(diagonalMovement)
16942 {
16943 switch(d2)
16944 {
16945 case up:
16946 if(shiftdir==left)
16947 {
16948 if(walkable)
16949 {
16950 dy-=1-z3diagskip;
16951 dx-=1-z3diagskip;
16952 z3step=2;
16953 }
16954 else
16955 {
16956 dx-=1-z3diagskip;
16957 z3step=2;
16958 }
16959 }
16960 else if(shiftdir==right)
16961 {
16962 if(walkable)
16963 {
16964 dy-=1-z3diagskip;
16965 dx+=1-z3diagskip;
16966 z3step=2;
16967 }
16968 else
16969 {
16970 dx+=1-z3diagskip;
16971 z3step=2;
16972 }
16973 }
16974 else
16975 {
16976 if(walkable)
16977 {
16978 dy-=z3step-z3skip;
16979 z3step=(z3step%2)+1;
16980 }
16981 }
16982
16983 break;
16984
16985 case down:
16986 if(shiftdir==left)
16987 {
16988 if(walkable)
16989 {
16990 dy+=1-z3diagskip;
16991 dx-=1-z3diagskip;
16992 z3step=2;
16993 }
16994 else
16995 {
16996 dx-=1-z3diagskip;
16997 z3step=2;
16998 }
16999 }
17000 else if(shiftdir==right)
17001 {
17002 if(walkable)
17003 {
17004 dy+=1-z3diagskip;
17005 dx+=1-z3diagskip;
17006 z3step=2;
17007 }
17008 else
17009 {
17010 dx+=1-z3diagskip;
17011 z3step=2;
17012 }
17013 }
17014 else
17015 {
17016 if(walkable)
17017 {
17018 dy+=z3step-z3skip;
17019 z3step=(z3step%2)+1;
17020 }
17021 }
17022
17023 break;
17024
17025 case right:
17026 if(shiftdir==up)
17027 {
17028 if(walkable)
17029 {
17030 dy-=1-z3diagskip;
17031 dx+=1-z3diagskip;
17032 z3step=2;
17033 }
17034 else
17035 {
17036 dy-=1-z3diagskip;
17037 z3step=2;
17038 }
17039 }
17040 else if(shiftdir==down)
17041 {
17042 if(walkable)
17043 {
17044 dy+=1-z3diagskip;
17045 dx+=1-z3diagskip;
17046 z3step=2;
17047 }
17048 else
17049 {
17050 dy+=1-z3diagskip;
17051 z3step=2;
17052 }
17053 }
17054 else
17055 {
17056 if(walkable)
17057 {
17058 dx+=z3step-z3skip;
17059 z3step=(z3step%2)+1;
17060 }
17061 }
17062
17063 break;
17064
17065 case left:
17066 if(shiftdir==up)
17067 {
17068 if(walkable)
17069 {
17070 dy-=1-z3diagskip;
17071 dx-=1-z3diagskip;
17072 z3step=2;
17073 }
17074 else
17075 {
17076 dy-=1-z3diagskip;
17077 z3step=2;
17078 }
17079 }
17080 else if(shiftdir==down)
17081 {
17082 if(walkable)
17083 {
17084 dy+=1-z3diagskip;
17085 dx-=1-z3diagskip;
17086 z3step=2;
17087 }
17088 else
17089 {
17090 dy+=1-z3diagskip;
17091 z3step=2;
17092 }
17093 }
17094 else
17095 {
17096 if(walkable)
17097 {
17098 dx-=z3step-z3skip;
17099 z3step=(z3step%2)+1;
17100 }
17101 }
17102
17103 break;
17104 }
17105 }
17106 else
17107 {
17108
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 264 times.
✓ Branch 2 taken 137 times.
✓ Branch 3 taken 233 times.
✓ Branch 4 taken 355 times.
989 switch(d2)
17109 {
17110 case up:
17111
1/14
✗ Branch 0 not taken.
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
264 if(!isSideViewHero() || (ladderx && laddery && ladderdir==up) || getOnSideviewLadder() || action == sideswimming || action == sideswimhit || action == sideswimattacking) dy-=ystep;
17112
17113 264 break;
17114
17115 case down:
17116
1/14
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
137 if(!isSideViewHero() || (ladderx && laddery && ladderdir==up) || getOnSideviewLadder() || action == sideswimming || action == sideswimhit || action == sideswimattacking) dy+=ystep;
17117
17118 137 break;
17119
17120 case left:
17121 233 dx-=xstep;
17122 233 break;
17123
17124 case right:
17125 355 dx+=xstep;
17126 355 break;
17127 }
17128 }
17129 989 }
17130
17131
5/16
✗ Branch 0 not taken.
✓ Branch 1 taken 989 times.
✓ Branch 2 taken 989 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 989 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 989 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 989 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
989 if((charging==0 || attack==wHammer) && spins==0 && attackclk!=HAMMERCHARGEFRAME && action != sideswimattacking && !(IsSideSwim() && get_bit(quest_rules,qr_SIDESWIMDIR) && (d2 == up || d2 == down))) //!DIRECTION SET
17132 {
17133 989 dir=d2;
17134 989 }
17135 else if (IsSideSwim() && get_bit(quest_rules,qr_SIDESWIMDIR) && (d2 == up || d2 == down) && (shiftdir == left || shiftdir == right) && (charging==0 && spins==0))
17136 {
17137 dir = shiftdir;
17138 }
17139
17140
2/4
✓ Branch 0 taken 989 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 989 times.
989 if(action != swimming && !IsSideSwim())
17141 {
17142 989 herostep();
17143
17144 //ack... don't walk if in midair! -DD
17145
5/14
✓ Branch 0 taken 989 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 989 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 989 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 989 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 989 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
989 if(charging==0 && spins==0 && z==0 && fakez==0 && !(isSideViewHero() && !on_sideview_solid_oldpos(x,y,old_x,old_y) && !getOnSideviewLadder()))
17146 {
17147 989 action=walking; FFCore.setHeroAction(walking);
17148 989 }
17149
17150
2/2
✓ Branch 0 taken 938 times.
✓ Branch 1 taken 51 times.
989 if(++hero_count > (16*hero_animation_speed))
17151 51 hero_count=0;
17152 989 }
17153 else if(!(frame & 1))
17154 {
17155 herostep();
17156 }
17157
17158
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 989 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
989 if(charging==0 || attack!=wHammer)
17159 {
17160 989 sprite::move((zfix)dx,(zfix)dy);
17161 989 }
17162 989 }
17163
17164 3550 HeroClass::WalkflagInfo HeroClass::walkflag(zfix fx,zfix fy,int32_t cnt,byte d2)
17165 {
17166 3550 return walkflag(fx.getInt(), fy.getInt(), cnt, d2);
17167 }
17168 3550 HeroClass::WalkflagInfo HeroClass::walkflag(int32_t wx,int32_t wy,int32_t cnt,byte d2)
17169 {
17170 3550 WalkflagInfo ret;
17171
17172 3550 wx = vbound(wx, -1, 256);
17173 3550 wy = vbound(wy, -1, 176);
17174
17175
7/8
✓ Branch 0 taken 3544 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3538 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 3538 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 3536 times.
3550 if (wx < 0 || wx > 255 || wy < 0 || wy > 175)
17176 {
17177 14 ret.setUnwalkable(false);
17178 14 return ret;
17179 }
17180
17181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3536 times.
3536 if(toogam)
17182 {
17183 ret.setUnwalkable(false);
17184 return ret;
17185 }
17186
17187
3/4
✓ Branch 0 taken 289 times.
✓ Branch 1 taken 3247 times.
✓ Branch 2 taken 289 times.
✗ Branch 3 not taken.
3536 if(blockpath && wy<(bigHitbox?80:88))
17188 {
17189 ret.setUnwalkable(true);
17190 return ret;
17191 }
17192
17193
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3536 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3536 if(blockmoving && mblock2.hit(wx,wy,0,1,1,1))
17194 {
17195 ret.setUnwalkable(true);
17196 return ret;
17197 }
17198
17199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3536 times.
3536 if (collide_object(wx, wy,1, 1))
17200 {
17201 ret.setUnwalkable(true);
17202 return ret;
17203 }
17204
17205
2/20
✗ Branch 0 not taken.
✓ Branch 1 taken 3536 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 3536 times.
3536 if(isdungeon() && currscr<128 && wy<(bigHitbox?32:40) && (((diagonalMovement||NO_GRIDLOCK)?(x<=112||x>=128):x!=120) || _walkflag(120,24,2,SWITCHBLOCK_STATE))
17206 && !get_bit(quest_rules,qr_FREEFORM))
17207 {
17208 ret.setUnwalkable(true);
17209 return ret;
17210 }
17211
17212
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3536 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3536 times.
3536 bool wf = _walkflag(wx,wy,cnt,SWITCHBLOCK_STATE);
17213
17214
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3536 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3536 if(isdungeon() && currscr<128 && !get_bit(quest_rules,qr_FREEFORM))
17215 {
17216 if((diagonalMovement||NO_GRIDLOCK))
17217 {
17218 if(wx>=112&&wx<120&&wy<40&&wy>=32) wf=true;
17219
17220 if(wx>=136&&wx<144&&wy<40&&wy>=32) wf=true;
17221 }
17222 }
17223 //All problems related to exiting water are probably here. -Z
17224
2/4
✓ Branch 0 taken 3536 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3536 times.
3536 if(action==swimming || IsSideSwim())
17225 {
17226 if(!wf)
17227 {
17228 bool isthissolid = false;
17229 if (_walkflag(x+7,y+(bigHitbox?6:11),1,SWITCHBLOCK_STATE)
17230 || _walkflag(x+7,y+(bigHitbox?9:12),1,SWITCHBLOCK_STATE)
17231 || _walkflag(x+8,y+(bigHitbox?6:11),1,SWITCHBLOCK_STATE)
17232 || _walkflag(x+8,y+(bigHitbox?9:12),1,SWITCHBLOCK_STATE)) isthissolid = true;
17233 //This checks if Hero is currently swimming in solid water (cause even if the QR "No Hopping" is enabled, he should still hop out of solid water) - Dimi
17234
17235
17236 if(landswim>= (get_bit(quest_rules,qr_DROWN) && isSwimming() ? 1
17237 : (!diagonalMovement) ? 1 : (get_bit(quest_rules,qr_NO_HOPPING)?1:22)))
17238 {
17239 //Check for out of bounds for swimming
17240 bool changehop = true;
17241
17242 if((diagonalMovement||NO_GRIDLOCK))
17243 {
17244 if(wx<0||wy<0)
17245 changehop = false;
17246 else if(wx>248)
17247 changehop = false;
17248 else if(wx>240&&cnt==2)
17249 changehop = false;
17250 else if(wy>168)
17251 changehop = false;
17252 }
17253 if ((get_bit(quest_rules, qr_NO_HOPPING) || CanSideSwim()) && !isthissolid) changehop = false;
17254 //This may be where the hang-up for exiting water exists. -Z
17255 // hop out of the water
17256 if(changehop)
17257 ret.setHopClk(1);
17258 }
17259 else
17260 {
17261 if((!(get_bit(quest_rules, qr_NO_HOPPING) || CanSideSwim()) || isthissolid) && (dir==d2 || shiftdir==d2))
17262 {
17263 //int32_t vx=((int32_t)x+4)&0xFFF8;
17264 //int32_t vy=((int32_t)y+4)&0xFFF8;
17265 if(d2==left)
17266 {
17267 if(!iswaterex(MAPCOMBO(x-1,y+(bigHitbox?6:11)), currmap, currscr, -1, x-1,y+(bigHitbox?6:11)) &&
17268 !iswaterex(MAPCOMBO(x-1,y+(bigHitbox?9:12)), currmap, currscr, -1, x-1,y+(bigHitbox?9:12)) &&
17269 !_walkflag(x-1,y+(bigHitbox?6:11),1,SWITCHBLOCK_STATE) &&
17270 !_walkflag(x-1,y+(bigHitbox?9:12),1,SWITCHBLOCK_STATE))
17271 {
17272 ret.setHopDir(d2);
17273 ret.setIlswim(true);
17274 }
17275 else ret.setIlswim(false);
17276 }
17277 else if(d2==right)
17278 {
17279 if(!iswaterex(MAPCOMBO(x+16,y+(bigHitbox?6:11)), currmap, currscr, -1, x+16,y+(bigHitbox?6:11)) &&
17280 !iswaterex(MAPCOMBO(x+16,y+(bigHitbox?9:12)), currmap, currscr, -1, x+16,y+(bigHitbox?9:12)) &&
17281 !_walkflag(x+16,y+(bigHitbox?6:11),1,SWITCHBLOCK_STATE) &&
17282 !_walkflag(x+16,y+(bigHitbox?9:12),1,SWITCHBLOCK_STATE))
17283 {
17284 ret.setHopDir(d2);
17285 ret.setIlswim(true);
17286 }
17287 else ret.setIlswim(false);
17288 }
17289 else if(d2==up)
17290 {
17291 if(!iswaterex(MAPCOMBO(x+7,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x+7,y+(bigHitbox?0:8)-1) &&
17292 !iswaterex(MAPCOMBO(x+8,y+(bigHitbox?0:8)-1), currmap, currscr, -1, x+8,y+(bigHitbox?0:8)-1) &&
17293 !_walkflag(x+7,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE) &&
17294 !_walkflag(x+8,y+(bigHitbox?0:8)-1,1,SWITCHBLOCK_STATE))
17295 {
17296 ret.setHopDir(d2);
17297 ret.setIlswim(true);
17298 }
17299 else ret.setIlswim(false);
17300 }
17301 else if(d2==down)
17302 {
17303 if(!iswaterex(MAPCOMBO(x+7,y+16), currmap, currscr, -1, x+7,y+16) &&
17304 !iswaterex(MAPCOMBO(x+8,y+16), currmap, currscr, -1, x+8,y+16) &&
17305 !_walkflag(x+7,y+16,1,SWITCHBLOCK_STATE) &&
17306 !_walkflag(x+8,y+16,1,SWITCHBLOCK_STATE))
17307 {
17308 ret.setHopDir(d2);
17309 ret.setIlswim(true);
17310 }
17311 else ret.setIlswim(false);
17312 }
17313 }
17314
17315 if(wx<0||wy<0);
17316 else if(wx>248);
17317 else if(wx>240&&cnt==2);
17318 else if(wy>168);
17319 else if(get_bit(quest_rules, qr_DROWN) && !ilswim);
17320 //if(iswaterex(MAPCOMBO(wx,wy)) && iswaterex(MAPCOMBO(wx,wy)))
17321 else if(iswaterex(MAPCOMBO(wx,wy), currmap, currscr, -1, wx,wy)) //!DIMI: weird duplicate function here before. Was water bugged this whole time, or was it just an unneccessary duplicate?
17322 {
17323 ret.setUnwalkable(false);
17324 return ret;
17325 }
17326 else
17327 {
17328 ret.setUnwalkable(true);
17329 return ret;
17330 }
17331 }
17332 }
17333 else
17334 {
17335 int32_t wtrx = iswaterex(MAPCOMBO(wx,wy), currmap, currscr, -1, wx,wy);
17336 int32_t wtrx8 = iswaterex(MAPCOMBO(x+8,wy), currmap, currscr, -1, x+8,wy); //!DIMI: Is x + 8 intentional???
17337
17338 if((d2>=left && wtrx) || (d2<=down && wtrx && wtrx8))
17339 {
17340 ret.setUnwalkable(false);
17341 return ret;
17342 }
17343 }
17344 }
17345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3536 times.
3536 else if(ladderx+laddery) // ladder is being used
17346 {
17347 int32_t lx = !(get_bit(quest_rules, qr_DROWN)&&iswaterex(MAPCOMBO(x+4,y+11), currmap, currscr, -1, x+4,y+11)&&!_walkflag(x+4,y+11,1,SWITCHBLOCK_STATE)) ? zfix(wx) : x;
17348 int32_t ly = !(get_bit(quest_rules, qr_DROWN)&&iswaterex(MAPCOMBO(x+4,y+11), currmap, currscr, -1, x+4,y+11)&&!_walkflag(x+4,y+11,1,SWITCHBLOCK_STATE)) ? zfix(wy) : y;
17349
17350 if((diagonalMovement||NO_GRIDLOCK))
17351 {
17352 if(ladderdir==up)
17353 {
17354 if(abs(ly-(laddery+8))<=8) // ly is between laddery (laddery+8-8) and laddery+16 (laddery+8+8)
17355 {
17356 bool temp = false;
17357
17358 if(!(abs(lx-(ladderx+8))<=8))
17359 temp = true;
17360
17361 if(cnt==2)
17362 if(!(abs((lx+8)-(ladderx+8))<=8))
17363 temp=true;
17364
17365 if(!temp)
17366 {
17367 ret.setUnwalkable(false);
17368 return ret;
17369 }
17370
17371 if(current_item_power(itype_ladder)<2 && (d2==left || d2==right) && !isSideViewHero())
17372 {
17373 ret.setUnwalkable(true);
17374 return ret;
17375 }
17376 }
17377 }
17378 else
17379 {
17380 if(abs(lx-(ladderx+8))<=8)
17381 {
17382 if(abs(ly-(laddery+(bigHitbox?8:12)))<=(bigHitbox?8:4))
17383 {
17384 ret.setUnwalkable(false);
17385 return ret;
17386 }
17387
17388 if(current_item_power(itype_ladder)<2 && (d2==up || d2==down))
17389 {
17390 ret.setUnwalkable(true);
17391 return ret;
17392 }
17393
17394 if((abs(ly-laddery+8)<=8) && d2<=down)
17395 {
17396 ret.setUnwalkable(false);
17397 return ret;
17398 }
17399 }
17400 }
17401 } // diagonalMovement
17402 else
17403 {
17404 if((d2&2)==ladderdir) // same direction
17405 {
17406 switch(d2)
17407 {
17408 case up:
17409 if(y.getInt()<=laddery)
17410 {
17411 ret.setUnwalkable(_walkflag(ladderx,laddery-8,1,SWITCHBLOCK_STATE) ||
17412 _walkflag(ladderx+8,laddery-8,1,SWITCHBLOCK_STATE));
17413 return ret;
17414
17415 }
17416
17417 [[fallthrough]];
17418 case down:
17419 if((wy&0xF0)==laddery)
17420 {
17421 ret.setUnwalkable(false);
17422 return ret;
17423 }
17424
17425 break;
17426
17427 default:
17428 if((wx&0xF0)==ladderx)
17429 {
17430 ret.setUnwalkable(false);
17431 return ret;
17432 }
17433 }
17434
17435 if(d2<=down)
17436 {
17437 ret.setUnwalkable(_walkflag(ladderx,wy,1,SWITCHBLOCK_STATE) || _walkflag(ladderx+8,wy,1,SWITCHBLOCK_STATE));
17438 return ret;
17439 }
17440
17441 ret.setUnwalkable(_walkflag((wx&0xF0),wy,1,SWITCHBLOCK_STATE) || _walkflag((wx&0xF0)+8,wy,1,SWITCHBLOCK_STATE));
17442 return ret;
17443 }
17444
17445 // different dir
17446 if(current_item_power(itype_ladder)<2 && !(isSideViewHero() && (d2==left || d2==right)))
17447 {
17448 ret.setUnwalkable(true);
17449 return ret;
17450 }
17451
17452 if(wy>=laddery && wy<=laddery+16 && d2<=down)
17453 {
17454 ret.setUnwalkable(false);
17455 return ret;
17456 }
17457 }
17458 }
17459
4/6
✓ Branch 0 taken 3382 times.
✓ Branch 1 taken 154 times.
✓ Branch 2 taken 3382 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3382 times.
3536 else if(wf || isSideViewHero() || get_bit(quest_rules, qr_DROWN))
17460 {
17461 // see if it's a good spot for the ladder or for swimming
17462
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 154 times.
154 bool unwalkablex = _walkflag(wx,wy,1,SWITCHBLOCK_STATE); //will be used later for the ladder -DD
17463
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 154 times.
154 bool unwalkablex8 = _walkflag(x+8,wy,1,SWITCHBLOCK_STATE);
17464
17465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if(get_bit(quest_rules, qr_DROWN))
17466 {
17467 // Drowning changes the following attributes:
17468 // * Dangerous water is also walkable, so ignore the previous
17469 // definitions of unwalkablex and unwalkablex8.
17470 // * Instead, prevent the ladder from being used in the
17471 // one frame where Hero has landed on water before drowning.
17472 unwalkablex = unwalkablex8 = !iswaterex(MAPCOMBO(x+4,y+11), currmap, currscr, -1, x+4,y+11);
17473 }
17474
17475 // check if he can swim
17476
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
154 if(current_item(itype_flippers) && z==0 && fakez==0)
17477 {
17478 int32_t wtrx = iswaterex(MAPCOMBO(wx,wy), currmap, currscr, -1, wx,wy);
17479 int32_t wtrx8 = iswaterex(MAPCOMBO(x+8,wy), currmap, currscr, -1, x+8,wy); //!DIMI: Still not sure if this should be x + 8...
17480 if (current_item(itype_flippers) >= combobuf[wtrx8].attribytes[0] && (!(combobuf[wtrx8].usrflags&cflag1) || (itemsbuf[current_item_id(itype_flippers)].flags & ITEM_FLAG3))) //Don't swim if the water's required level is too high! -Dimi
17481 {
17482 //ladder ignores water combos that are now walkable thanks to flippers -DD
17483 unwalkablex = unwalkablex && (!wtrx);
17484 unwalkablex8 = unwalkablex8 && (!wtrx8);
17485
17486 if(landswim >= 22)
17487 {
17488 ret.setHopClk(2);
17489 ret.setUnwalkable(false);
17490 return ret;
17491 }
17492 else if((d2>=left && wtrx) || (d2<=down && wtrx && wtrx8))
17493 {
17494 if(!(diagonalMovement||NO_GRIDLOCK))
17495 {
17496 ret.setHopClk(2);
17497
17498 if(charging || spins>5)
17499 {
17500 //if Hero is charging, he might be facing the wrong direction (we want him to
17501 //hop into the water, not in the facing direction)
17502 ret.setDir(d2);
17503 //moreover Hero can't charge in the water -DD
17504 ret.setChargeAttack();
17505 }
17506
17507 ret.setUnwalkable(false);
17508 return ret;
17509 }
17510 else if(dir==d2)
17511 {
17512 ret.setIlswim(true);
17513 ladderx = 0;
17514 laddery = 0;
17515 }
17516 }
17517 }
17518 }
17519
17520 // check if he can use the ladder
17521 // "Allow Ladder Anywhere" is toggled by fLADDER
17522
1/2
✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
154 if(can_deploy_ladder())
17523 // laddersetup
17524 {
17525 // Check if there's water to use the ladder over
17526 bool wtrx = (iswaterex(MAPCOMBO(wx,wy), currmap, currscr, -1, wx,wy) != 0);
17527 bool wtrx8 = (iswaterex(MAPCOMBO(x+8,wy), currmap, currscr, -1, x+8,wy) != 0);
17528 int32_t ldrid = current_item_id(itype_ladder);
17529 bool ladderpits = ldrid > -1 && (itemsbuf[ldrid].flags&ITEM_FLAG1);
17530
17531 if(wtrx || wtrx8)
17532 {
17533 if(isSideViewHero())
17534 {
17535 wtrx = !_walkflag(wx, wy+8, 1,SWITCHBLOCK_STATE) && !_walkflag(wx, wy, 1,SWITCHBLOCK_STATE) && dir!=down;
17536 wtrx8 = !_walkflag(wx+8, wy+8, 1,SWITCHBLOCK_STATE) && !_walkflag(wx+8, wy, 1,SWITCHBLOCK_STATE) && dir!=down;
17537 }
17538 // * walk on half-water using the ladder instead of using flippers.
17539 // * otherwise, walk on ladder(+hookshot) combos.
17540 else if(wtrx==wtrx8 && (isstepable(MAPCOMBO(wx, wy)) || isstepable(MAPCOMBO(wx+8,wy)) || wtrx==true))
17541 {
17542 if(!get_bit(quest_rules, qr_OLD_210_WATER))
17543 {
17544 //if Hero could swim on a tile instead of using the ladder,
17545 //refuse to use the ladder to step over that tile. -DD
17546 wtrx = isstepable(MAPCOMBO(wx, wy)) && unwalkablex;
17547 wtrx8 = isstepable(MAPCOMBO(wx+8,wy)) && unwalkablex8;
17548 }
17549 }
17550 }
17551 else
17552 {
17553 // No water; check other things
17554
17555 //Check pits
17556 if(ladderpits)
17557 {
17558 int32_t pit_cmb = getpitfall(wx,wy);
17559 wtrx = pit_cmb && (combobuf[pit_cmb].usrflags&cflag4);
17560 pit_cmb = getpitfall(x+8,wy);
17561 wtrx8 = pit_cmb && (combobuf[pit_cmb].usrflags&cflag4);
17562 }
17563 if(!ladderpits || (!(wtrx || wtrx8) || isSideViewHero())) //If no pit, check ladder combos
17564 {
17565 int32_t combo=combobuf[MAPCOMBO(wx, wy)].type;
17566 wtrx=(combo==cLADDERONLY || combo==cLADDERHOOKSHOT);
17567 combo=combobuf[MAPCOMBO(wx+8, wy)].type;
17568 wtrx8=(combo==cLADDERONLY || combo==cLADDERHOOKSHOT);
17569 }
17570 }
17571
17572 for (int32_t i = 0; i <= 1; ++i)
17573 {
17574 if(tmpscr2[i].valid!=0)
17575 {
17576 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
17577 {
17578 if (combobuf[MAPCOMBO2(i,wx,wy)].type == cBRIDGE && !_walkflag_layer(wx,wy,1, &(tmpscr2[i]))) wtrx = false;
17579 if (combobuf[MAPCOMBO2(i,wx+8,wy)].type == cBRIDGE && !_walkflag_layer(wx+8,wy,1, &(tmpscr2[i]))) wtrx8 = false;
17580 }
17581 else
17582 {
17583 if (combobuf[MAPCOMBO2(i,wx,wy)].type == cBRIDGE && _effectflag_layer(wx,wy,1, &(tmpscr2[i]))) wtrx = false;
17584 if (combobuf[MAPCOMBO2(i,wx+8,wy)].type == cBRIDGE && _effectflag_layer(wx+8,wy,1, &(tmpscr2[i]))) wtrx8 = false;
17585 }
17586 }
17587 }
17588 bool walkwater = (get_bit(quest_rules, qr_DROWN) && !iswaterex(MAPCOMBO(wx,wy), currmap, currscr, -1, wx,wy));
17589
17590 if((diagonalMovement||NO_GRIDLOCK))
17591 {
17592 if(d2==dir)
17593 {
17594 int32_t c = walkwater ? 0:8;
17595 int32_t b = walkwater ? 8:0;
17596
17597 if(d2>=left)
17598 {
17599 // If the difference between wy and y is small enough
17600 if(abs((wy)-(int32_t(y+c)))<=(b) && wtrx)
17601 {
17602 // Don't activate the ladder if it would be entirely
17603 // over water and Hero has the flippers. This isn't
17604 // a good way to do this, but it's too risky
17605 // to make big changes to this stuff.
17606 bool deployLadder=true;
17607 int32_t lx=wx&0xF0;
17608 if(current_item(itype_flippers) && current_item(itype_flippers) >= combobuf[iswaterex(MAPCOMBO(lx+8, y+8), currmap, currscr, -1, lx+8, y+8)].attribytes[0] && z==0 && fakez==0)
17609 {
17610 if(iswaterex(MAPCOMBO(lx, y), currmap, currscr, -1, lx, y) &&
17611 iswaterex(MAPCOMBO(lx+15, y), currmap, currscr, -1, lx+15, y) &&
17612 iswaterex(MAPCOMBO(lx, y+15), currmap, currscr, -1, lx, y+15) &&
17613 iswaterex(MAPCOMBO(lx+15, y+15), currmap, currscr, -1, lx+15, y+15))
17614 deployLadder=false;
17615 }
17616 if(deployLadder)
17617 {
17618 ladderx = wx&0xF0;
17619 laddery = y;
17620 ladderdir = left;
17621 ladderstart = d2;
17622 ret.setUnwalkable(laddery!=y.getInt());
17623 return ret;
17624 }
17625 }
17626 }
17627 else if(d2<=down)
17628 {
17629 // If the difference between wx and x is small enough
17630 if(abs((wx)-(int32_t(x+c)))<=(b) && wtrx)
17631 {
17632 ladderx = x;
17633 laddery = wy&0xF0;
17634 ladderdir = up;
17635 ladderstart = d2;
17636 ret.setUnwalkable(ladderx!=x.getInt());
17637 return ret;
17638 }
17639
17640 if(cnt==2)
17641 {
17642 if(abs((wx+8)-(int32_t(x+c)))<=(b) && wtrx8)
17643 {
17644 ladderx = x;
17645 laddery = wy&0xF0;
17646 ladderdir = up;
17647 ladderstart = d2;
17648 ret.setUnwalkable(ladderx!=x.getInt());
17649 return ret;
17650 }
17651 }
17652 }
17653 }
17654 }
17655 else
17656 {
17657 bool flgx = _walkflag(wx,wy,1,SWITCHBLOCK_STATE) && !wtrx; // Solid, and not steppable
17658 bool flgx8 = _walkflag(x+8,wy,1,SWITCHBLOCK_STATE) && !wtrx8; // Solid, and not steppable
17659
17660 if((d2>=left && wtrx)
17661 // Deploy the ladder vertically even if Hero is only half on water.
17662 || (d2<=down && ((wtrx && !flgx8) || (wtrx8 && !flgx))))
17663 {
17664 if(((y.getInt()+15) < wy) || ((y.getInt()+8) > wy))
17665 ladderdir = up;
17666 else
17667 ladderdir = left;
17668
17669 if(ladderdir==up)
17670 {
17671 ladderx = x.getInt()&0xF8;
17672 laddery = wy&0xF0;
17673 }
17674 else
17675 {
17676 ladderx = wx&0xF0;
17677 laddery = y.getInt()&0xF8;
17678 }
17679
17680 ret.setUnwalkable(false);
17681 return ret;
17682 }
17683 }
17684 }
17685 154 }
17686
17687 3536 ret.setUnwalkable(wf);
17688 3536 return ret;
17689 3550 }
17690
17691 // Only checks for moving blocks. Apparently this is a thing we need.
17692 428 HeroClass::WalkflagInfo HeroClass::walkflagMBlock(int32_t wx,int32_t wy)
17693 {
17694 428 HeroClass::WalkflagInfo ret;
17695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 428 times.
428 if (!blockmoving) //Without this, weird swimming behaviors happen.
17696 {
17697 428 ret.setFlags(~1);
17698 428 ret.setHopDir(-1);
17699 428 }
17700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 428 times.
428 if(toogam) return ret;
17701
1/2
✓ Branch 0 taken 428 times.
✗ Branch 1 not taken.
428 if (blockmoving)
17702 ret.setUnwalkable(mblock2.hit(wx,wy,0,1,1,1));
17703
1/2
✓ Branch 0 taken 428 times.
✗ Branch 1 not taken.
428 if (collide_object(wx, wy,1, 1))
17704 ret.setUnwalkable(true);
17705 428 return ret;
17706 428 }
17707
17708 1888 bool HeroClass::checksoliddamage()
17709 {
17710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(toogam) return false;
17711
17712
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1888 times.
1888 if(z!=0||fakez!=0) return false;
17713 1888 int32_t bx = x.getInt();
17714 1888 int32_t by = y.getInt();
17715 1888 int32_t initk = 0;
17716
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 595 times.
✓ Branch 2 taken 173 times.
✓ Branch 3 taken 399 times.
✓ Branch 4 taken 721 times.
1888 switch(dir)
17717 {
17718 case up:
17719
17720 595 by-=bigHitbox ? 4 : -4;
17721
17722
1/2
✓ Branch 0 taken 595 times.
✗ Branch 1 not taken.
595 if(by<0)
17723 {
17724 return false;
17725 }
17726 595 break;
17727
17728 case down:
17729
17730 173 by+=20;
17731
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 169 times.
173 if(by>175)
17732 {
17733 4 return false;
17734 }
17735
17736 169 break;
17737
17738 case left:
17739 399 bx-=4;
17740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 399 times.
399 if (!bigHitbox)
17741 {
17742 399 by+=8;
17743 399 initk = 1;
17744 399 }
17745
2/2
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 3 times.
399 if(bx<0)
17746 {
17747 3 return false;
17748 }
17749
17750 396 break;
17751
17752 case right:
17753
17754 721 bx+=20;
17755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 721 times.
721 if (!bigHitbox)
17756 {
17757 721 by+=8;
17758 721 initk = 1;
17759 721 }
17760
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 717 times.
721 if(bx>255)
17761 {
17762 4 return false;
17763 }
17764
17765 717 break;
17766 }
17767 1877 newcombo const& cmb = combobuf[MAPCOMBO(bx,by)];
17768 1877 int32_t t = cmb.type;
17769
1/2
✓ Branch 0 taken 1877 times.
✗ Branch 1 not taken.
1877 if(cmb.triggerflags[0] & combotriggerONLYGENTRIG)
17770 t = cNONE;
17771 1877 int32_t initbx = bx;
17772 1877 int32_t initby = by;
17773
17774 // Unlike push blocks, damage combos should be tested on layers 2 and under
17775
2/2
✓ Branch 0 taken 1877 times.
✓ Branch 1 taken 1877 times.
3754 for(int32_t i=(get_bit(quest_rules,qr_DMGCOMBOLAYERFIX) ? 2 : 0); i>=0; i--)
17776 {
17777 1877 bx = initbx;
17778 1877 by = initby;
17779
2/2
✓ Branch 0 taken 4518 times.
✓ Branch 1 taken 1877 times.
6395 for (int32_t k = initk; k <= 2; k++)
17780 {
17781 4518 newcombo const& cmb = combobuf[FFCore.tempScreens[i]->data[COMBOPOS(bx,by)]];
17782 4518 t = cmb.type;
17783
1/2
✓ Branch 0 taken 4518 times.
✗ Branch 1 not taken.
4518 if(cmb.triggerflags[0] & combotriggerONLYGENTRIG)
17784 t = cNONE;
17785 // Solid damage combos use pushing>0, hence the code is here.
17786
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 4518 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
4518 if (!get_bit(quest_rules, qr_LESS_AWFUL_SIDESPIKES) || !isSideViewHero() || (dir != down && (dir != up || getOnSideviewLadder())))
17787 {
17788
2/18
✓ Branch 0 taken 4518 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 4518 times.
✗ Branch 17 not taken.
4518 if(combo_class_buf[t].modify_hp_amount && _walkflag(bx,by,1,SWITCHBLOCK_STATE) && pushing>0 && hclk<1 && action!=casting && action != sideswimcasting && !get_bit(quest_rules, qr_NOSOLIDDAMAGECOMBOS))
17789 {
17790 // Bite Hero
17791 if (checkdamagecombos(bx, bx, by, by, i-1, true)) return true;
17792 }
17793 4518 }
17794
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4518 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4518 if(isSideViewHero() && // Check for sideview damage combos
17795 hclk<1 && action!=casting && action!=sideswimcasting) // ... but only if Hero could be hurt
17796 {
17797 if (get_bit(quest_rules, qr_LESS_AWFUL_SIDESPIKES))
17798 {
17799 if (on_sideview_solid_oldpos(x,y,old_x,old_y) && (!getOnSideviewLadder() || DrunkDown()))
17800 {
17801 if(checkdamagecombos(x+4, x+4, y+16, y+18, i-1, false, false) && checkdamagecombos(x+12, x+12, y+16, y+18, i-1, false, false))
17802 {
17803 if (checkdamagecombos(x+4, x+12, y+16, y+18, i-1, false, true)) return true;
17804 }
17805 }
17806 if (checkdamagecombos(x+4, x+12, y+8, y+15, i-1, false, true)) return true;
17807 }
17808 else
17809 {
17810 //old 2.50.2-ish code for 2.50.0 sideview quests for er_OLDSIDEVIEWSPIKES
17811 if ( get_bit(quest_rules, qr_OLDSIDEVIEWSPIKES ) )
17812 {
17813 if (checkdamagecombos(x+8-(zfix)(tmpscr->csensitive),
17814 x+8+(zc_max(tmpscr->csensitive-1,0)),
17815 y+17-(get_bit(quest_rules,qr_LTTPCOLLISION)?tmpscr->csensitive:(tmpscr->csensitive+1)/2),
17816 y+17+zc_max((get_bit(quest_rules,qr_LTTPCOLLISION)?tmpscr->csensitive:(tmpscr->csensitive+1)/2)-1,0), i-1, true))
17817 return true;
17818 }
17819 else //2.50.1 and later
17820 {
17821 if(checkdamagecombos(x+4, x+12, y+16, y+24))
17822 return true;
17823 }
17824 }
17825
17826 }
17827
2/2
✓ Branch 0 taken 2292 times.
✓ Branch 1 taken 2226 times.
4518 if (dir < left) bx += (k % 2) ? 7 : 8;
17828 2226 else by += (k % 2) ? 7 : 8;
17829 4518 }
17830 1877 }
17831 1877 return false;
17832 1888 }
17833 1888 void HeroClass::checkpushblock()
17834 {
17835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(toogam) return;
17836
17837
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1888 times.
1888 if(z!=0||fakez!=0) return;
17838
17839 // Return early in some cases..
17840 1888 bool earlyReturn=false;
17841
17842
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
1888 if(!(diagonalMovement||NO_GRIDLOCK) || dir==left)
17843
2/2
✓ Branch 0 taken 658 times.
✓ Branch 1 taken 1230 times.
1888 if(x.getInt()&15) earlyReturn=true;
17844
17845 // if(y<16) return;
17846
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if(isSideViewHero() && !on_sideview_solid_oldpos(x,y,old_x,old_y)) return;
17847
17848 1888 int32_t bx = x.getInt()&0xF0;
17849 1888 int32_t by = (y.getInt()&0xF0);
17850
17851
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 595 times.
✓ Branch 2 taken 173 times.
✓ Branch 3 taken 399 times.
✓ Branch 4 taken 721 times.
1888 switch(dir)
17852 {
17853 case up:
17854
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 583 times.
595 if(y<16)
17855 {
17856 12 earlyReturn=true;
17857 12 break;
17858 }
17859
17860
3/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 558 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25 times.
583 if(!((int32_t)y&15)&&y!=0) by-=bigHitbox ? 16 : 0;
17861
17862
2/2
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 126 times.
583 if((int32_t)x&8) bx+=16;
17863
17864 583 break;
17865
17866 case down:
17867
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 149 times.
173 if(y>128)
17868 {
17869 24 earlyReturn=true;
17870 24 break;
17871 }
17872 else
17873 {
17874 149 by+=16;
17875
17876
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 38 times.
149 if((int32_t)x&8) bx+=16;
17877 }
17878
17879 149 break;
17880
17881 case left:
17882
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 375 times.
399 if(x<32)
17883 {
17884 24 earlyReturn=true;
17885 24 break;
17886 }
17887 else
17888 {
17889 375 bx-=16;
17890
17891
2/2
✓ Branch 0 taken 276 times.
✓ Branch 1 taken 99 times.
375 if(y.getInt()&8)
17892 {
17893 99 by+=16;
17894 99 }
17895 }
17896
17897 375 break;
17898
17899 case right:
17900
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 697 times.
721 if(x>208)
17901 {
17902 24 earlyReturn=true;
17903 24 break;
17904 }
17905 else
17906 {
17907 697 bx+=16;
17908
17909
2/2
✓ Branch 0 taken 488 times.
✓ Branch 1 taken 209 times.
697 if(y.getInt()&8)
17910 {
17911 209 by+=16;
17912 209 }
17913 }
17914
17915 697 break;
17916 }
17917
17918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if (checksoliddamage()) return;
17919
17920
2/2
✓ Branch 0 taken 1234 times.
✓ Branch 1 taken 654 times.
1888 if(earlyReturn)
17921 1234 return;
17922
17923 654 int32_t itemid=current_item_id(itype_bracelet);
17924 654 size_t combopos = (by&0xF0)+(bx>>4);
17925
1/2
✓ Branch 0 taken 654 times.
✗ Branch 1 not taken.
654 bool limitedpush = (itemid>=0 && itemsbuf[itemid].flags & ITEM_FLAG1);
17926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 654 times.
654 itemdata const* glove = itemid < 0 ? NULL : &itemsbuf[itemid];
17927
2/2
✓ Branch 0 taken 654 times.
✓ Branch 1 taken 1962 times.
2616 for(int lyr = 2; lyr > -1; --lyr) //Top-down, in case of stacked push blocks
17928 {
17929
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1962 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1962 if(get_bit(quest_rules,qr_HESITANTPUSHBLOCKS)&&(pushing<4)) break;
17930
3/4
✓ Branch 0 taken 1308 times.
✓ Branch 1 taken 654 times.
✓ Branch 2 taken 1308 times.
✗ Branch 3 not taken.
1962 if(lyr && !get_bit(quest_rules, qr_PUSHBLOCK_LAYER_1_2))
17931 1308 continue;
17932 654 mapscr* m = FFCore.tempScreens[lyr];
17933 654 int32_t f = MAPFLAG2(lyr-1,bx,by);
17934 654 int32_t f2 = MAPCOMBOFLAG2(lyr-1,bx,by);
17935 654 int32_t t = combobuf[MAPCOMBOL(lyr,bx,by)].type;
17936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 654 times.
654 if (lyr == 0) t = combobuf[MAPCOMBO(bx,by)].type;
17937
17938
5/8
✓ Branch 0 taken 654 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 654 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 654 times.
✓ Branch 6 taken 654 times.
✓ Branch 7 taken 654 times.
654 if((t==cPUSH_WAIT || t==cPUSH_HW || t==cPUSH_HW2) && (pushing<16 || hasMainGuy())) continue;
17939
17940
6/8
✓ Branch 0 taken 654 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✓ Branch 3 taken 53 times.
✓ Branch 4 taken 601 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 53 times.
✓ Branch 7 taken 601 times.
707 if((t==cPUSH_HW || t==cPUSH_HEAVY || t==cPUSH_HEAVY2 || t==cPUSH_HW2)
17941
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 601 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 53 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
654 && (itemid<0 || glove->power<((t==cPUSH_HEAVY2 || t==cPUSH_HW2)?2:1) ||
17942
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
53 (limitedpush && usecounts[itemid] > zc_max(1, glove->misc3)))) continue;
17943
17944 601 bool doit=false;
17945 601 bool changeflag=false;
17946 601 bool changecombo=false;
17947
17948
4/8
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 601 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 601 times.
1202 if(((f==mfPUSHUD || f==mfPUSHUDNS|| f==mfPUSHUDINS) && dir<=down) ||
17949
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
601 ((f==mfPUSHLR || f==mfPUSHLRNS|| f==mfPUSHLRINS) && dir>=left) ||
17950
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
601 ((f==mfPUSHU || f==mfPUSHUNS || f==mfPUSHUINS) && dir==up) ||
17951
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
601 ((f==mfPUSHD || f==mfPUSHDNS || f==mfPUSHDINS) && dir==down) ||
17952
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
601 ((f==mfPUSHL || f==mfPUSHLNS || f==mfPUSHLINS) && dir==left) ||
17953
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
601 ((f==mfPUSHR || f==mfPUSHRNS || f==mfPUSHRINS) && dir==right) ||
17954
1/2
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
601 f==mfPUSH4 || f==mfPUSH4NS || f==mfPUSH4INS)
17955 {
17956 changeflag=true;
17957 doit=true;
17958 }
17959
17960
4/8
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 601 times.
✓ Branch 6 taken 601 times.
✗ Branch 7 not taken.
1202 if((((f2==mfPUSHUD || f2==mfPUSHUDNS|| f2==mfPUSHUDINS) && dir<=down) ||
17961
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
601 ((f2==mfPUSHLR || f2==mfPUSHLRNS|| f2==mfPUSHLRINS) && dir>=left) ||
17962
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
601 ((f2==mfPUSHU || f2==mfPUSHUNS || f2==mfPUSHUINS) && dir==up) ||
17963
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
601 ((f2==mfPUSHD || f2==mfPUSHDNS || f2==mfPUSHDINS) && dir==down) ||
17964
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
601 ((f2==mfPUSHL || f2==mfPUSHLNS || f2==mfPUSHLINS) && dir==left) ||
17965
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
601 ((f2==mfPUSHR || f2==mfPUSHRNS || f2==mfPUSHRINS) && dir==right) ||
17966
1/2
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
601 f2==mfPUSH4 || f2==mfPUSH4NS || f2==mfPUSH4INS)&&(f!=mfPUSHED))
17967 {
17968 changecombo=true;
17969 doit=true;
17970 }
17971
17972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 601 times.
601 if(get_bit(quest_rules,qr_SOLIDBLK))
17973 {
17974 switch(dir)
17975 {
17976 case up:
17977 if(_walkflag(bx,by-8,2,SWITCHBLOCK_STATE)&&!(MAPFLAG2(lyr-1,bx,by-8)==mfBLOCKHOLE||MAPCOMBOFLAG2(lyr-1,bx,by-8)==mfBLOCKHOLE)) doit=false;
17978
17979 break;
17980
17981 case down:
17982 if(_walkflag(bx,by+24,2,SWITCHBLOCK_STATE)&&!(MAPFLAG2(lyr-1,bx,by+24)==mfBLOCKHOLE||MAPCOMBOFLAG2(lyr-1,bx,by+24)==mfBLOCKHOLE)) doit=false;
17983
17984 break;
17985
17986 case left:
17987 if(_walkflag(bx-16,by+8,2,SWITCHBLOCK_STATE)&&!(MAPFLAG2(lyr-1,bx-16,by+8)==mfBLOCKHOLE||MAPCOMBOFLAG2(lyr-1,bx-16,by+8)==mfBLOCKHOLE)) doit=false;
17988
17989 break;
17990
17991 case right:
17992 if(_walkflag(bx+16,by+8,2,SWITCHBLOCK_STATE)&&!(MAPFLAG2(lyr-1,bx+16,by+8)==mfBLOCKHOLE||MAPCOMBOFLAG2(lyr-1,bx+16,by+8)==mfBLOCKHOLE)) doit=false;
17993
17994 break;
17995 }
17996 }
17997
17998
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
✓ Branch 2 taken 82 times.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 45 times.
601 switch(dir)
17999 {
18000 case up:
18001
2/4
✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 457 times.
457 if((MAPFLAG2(lyr-1,bx,by-8)==mfNOBLOCKS||MAPCOMBOFLAG2(lyr-1,bx,by-8)==mfNOBLOCKS)) doit=false;
18002
18003 457 break;
18004
18005 case down:
18006
2/4
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 82 times.
82 if((MAPFLAG2(lyr-1,bx,by+24)==mfNOBLOCKS||MAPCOMBOFLAG2(lyr-1,bx,by+24)==mfNOBLOCKS)) doit=false;
18007
18008 82 break;
18009
18010 case left:
18011
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
17 if((MAPFLAG2(lyr-1,bx-16,by+8)==mfNOBLOCKS||MAPCOMBOFLAG2(lyr-1,bx-16,by+8)==mfNOBLOCKS)) doit=false;
18012
18013 17 break;
18014
18015 case right:
18016
2/4
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 45 times.
45 if((MAPFLAG2(lyr-1,bx+16,by+8)==mfNOBLOCKS||MAPCOMBOFLAG2(lyr-1,bx+16,by+8)==mfNOBLOCKS)) doit=false;
18017
18018 45 break;
18019 }
18020
18021
1/2
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
601 if(doit)
18022 {
18023 if(limitedpush)
18024 ++usecounts[itemid];
18025
18026 // for(int32_t i=0; i<1; i++)
18027 if(!blockmoving)
18028 {
18029 if(changeflag)
18030 {
18031 m->sflag[combopos]=0;
18032 }
18033
18034 if(mblock2.clk<=0)
18035 {
18036 mblock2.blockLayer = lyr;
18037 mblock2.push((zfix)bx,(zfix)by,dir,f);
18038
18039 if(get_bit(quest_rules,qr_MORESOUNDS))
18040 sfx(WAV_ZN1PUSHBLOCK,(int32_t)x);
18041 }
18042 }
18043 break;
18044 }
18045 601 }
18046 1888 }
18047
18048 bool usekey()
18049 {
18050 int32_t itemid = current_item_id(itype_magickey);
18051
18052 if(itemid<0 ||
18053 (itemsbuf[itemid].flags & ITEM_FLAG1 ? itemsbuf[itemid].power<dlevel
18054 : itemsbuf[itemid].power!=dlevel))
18055 {
18056 if(game->lvlkeys[dlevel]!=0)
18057 {
18058 game->lvlkeys[dlevel]--;
18059 //run script for level key item
18060 int32_t key_item = 0; //current_item_id(itype_lkey); //not possible
18061 for ( int32_t q = 0; q < MAXITEMS; ++q )
18062 {
18063 if ( itemsbuf[q].family == itype_lkey )
18064 {
18065 key_item = q; break;
18066 }
18067 }
18068
18069 if ( key_item > 0 && itemsbuf[key_item].script && !(item_doscript[key_item] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) )
18070 {
18071 ri = &(itemScriptData[key_item]);
18072 for ( int32_t q = 0; q < 1024; q++ ) item_stack[key_item][q] = 0xFFFF;
18073 ri->Clear();
18074 item_doscript[key_item] = 1;
18075 itemscriptInitialised[key_item] = 0;
18076 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[key_item].script, key_item);
18077 FFCore.deallocateAllArrays(SCRIPT_ITEM,(key_item));
18078 }
18079 return true;
18080 }
18081 else
18082 {
18083 if(game->get_keys()==0)
18084 {
18085 return false;
18086 }
18087 else
18088 {
18089 //run script for key item
18090 int32_t key_item = 0; //current_item_id(itype_key); //not possible
18091 for ( int32_t q = 0; q < MAXITEMS; ++q )
18092 {
18093 if ( itemsbuf[q].family == itype_key )
18094 {
18095 key_item = q; break;
18096 }
18097 }
18098 //zprint2("key_item is: %d\n",key_item);
18099 //zprint2("key_item script is: %d\n",itemsbuf[key_item].script);
18100 if ( key_item > 0 && itemsbuf[key_item].script && !(item_doscript[key_item] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) )
18101 {
18102 ri = &(itemScriptData[key_item]);
18103 for ( int32_t q = 0; q < 1024; q++ ) item_stack[key_item][q] = 0xFFFF;
18104 ri->Clear();
18105 item_doscript[key_item] = 1;
18106 itemscriptInitialised[key_item] = 0;
18107 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[key_item].script, key_item);
18108 FFCore.deallocateAllArrays(SCRIPT_ITEM,(key_item));
18109 }
18110 game->change_keys(-1);
18111 }
18112 }
18113 }
18114
18115 return true;
18116 }
18117
18118 bool canUseKey(int32_t num)
18119 {
18120 int32_t itemid = current_item_id(itype_magickey);
18121
18122 if(itemid<0 ||
18123 (itemsbuf[itemid].flags & ITEM_FLAG1 ? itemsbuf[itemid].power<dlevel
18124 : itemsbuf[itemid].power!=dlevel))
18125 {
18126 return game->lvlkeys[dlevel] + game->get_keys() >= num;
18127 }
18128
18129 return true;
18130 }
18131
18132 bool usekey(int32_t num)
18133 {
18134 if(!canUseKey(num)) return false;
18135 for(auto q = 0; q < num; ++q)
18136 {
18137 if(!usekey()) return false; //should never return false here, but, just to be safe....
18138 }
18139 return true;
18140 }
18141
18142
18143 bool islockeddoor(int32_t x, int32_t y, int32_t lock)
18144 {
18145 int32_t mc = (y&0xF0)+(x>>4);
18146 bool ret = (((mc==7||mc==8||mc==23||mc==24) && tmpscr->door[up]==lock)
18147 || ((mc==151||mc==152||mc==167||mc==168) && tmpscr->door[down]==lock)
18148 || ((mc==64||mc==65||mc==80||mc==81) && tmpscr->door[left]==lock)
18149 || ((mc==78||mc==79||mc==94||mc==95) && tmpscr->door[right]==lock));
18150 return ret;
18151 }
18152
18153 1888 void HeroClass::oldchecklockblock()
18154 {
18155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(toogam) return;
18156
18157 1888 int32_t bx = x.getInt()&0xF0;
18158 1888 int32_t bx2 = int32_t(x+8)&0xF0;
18159 1888 int32_t by = y.getInt()&0xF0;
18160
18161
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 595 times.
✓ Branch 2 taken 173 times.
✓ Branch 3 taken 399 times.
✓ Branch 4 taken 721 times.
1888 switch(dir)
18162 {
18163 case up:
18164
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 569 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 25 times.
595 if(!((int32_t)y&15)&&y!=0) by-=bigHitbox ? 16 : 0;
18165
18166 595 break;
18167
18168 case down:
18169 173 by+=16;
18170 173 break;
18171
18172 case left:
18173
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 270 times.
399 if((((int32_t)x)&0x0F)<8)
18174 270 bx-=16;
18175
18176
2/2
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 99 times.
399 if(y.getInt()&8)
18177 {
18178 99 by+=16;
18179 99 }
18180
18181 399 bx2=bx;
18182 399 break;
18183
18184 case right:
18185 721 bx+=16;
18186
18187
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 209 times.
721 if(y.getInt()&8)
18188 {
18189 209 by+=16;
18190 209 }
18191
18192 721 bx2=bx;
18193 721 break;
18194 }
18195
18196 1888 bool found1=false;
18197 1888 bool found2=false;
18198 1888 int32_t foundlayer = -1;
18199 1888 int32_t cid1 = MAPCOMBO(bx, by), cid2 = MAPCOMBO(bx2, by);
18200 1888 newcombo const& cmb = combobuf[cid1];
18201 1888 newcombo const& cmb2 = combobuf[cid2];
18202 // Layer 0 is overridden by Locked Doors
18203
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1888 if((cmb.type==cLOCKBLOCK && !(cmb.triggerflags[0] & combotriggerONLYGENTRIG) && _effectflag(bx,by,1, -1) && !islockeddoor(bx,by,dLOCKED)))
18204 {
18205 found1=true;
18206 foundlayer = 0;
18207 }
18208
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1888 else if (cmb2.type==cLOCKBLOCK && !(cmb2.triggerflags[0] & combotriggerONLYGENTRIG) && _effectflag(bx2,by,1, -1) && !islockeddoor(bx2,by,dLOCKED))
18209 {
18210 found2=true;
18211 foundlayer = 0;
18212 }
18213
18214
2/2
✓ Branch 0 taken 3776 times.
✓ Branch 1 taken 1888 times.
5664 for (int32_t i = 0; i <= 1; ++i)
18215 {
18216
1/2
✓ Branch 0 taken 3776 times.
✗ Branch 1 not taken.
3776 if(tmpscr2[i].valid!=0)
18217 {
18218 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
18219 {
18220 if (combobuf[MAPCOMBO2(i,bx,by)].type == cBRIDGE && !_walkflag_layer(bx,by,1, &(tmpscr2[i]))) found1 = false;
18221 if (combobuf[MAPCOMBO2(i,bx2,by)].type == cBRIDGE && !_walkflag_layer(bx2,by,1, &(tmpscr2[i]))) found2 = false;
18222 }
18223 else
18224 {
18225 if (combobuf[MAPCOMBO2(i,bx,by)].type == cBRIDGE && _effectflag_layer(bx,by,1, &(tmpscr2[i]))) found1 = false;
18226 if (combobuf[MAPCOMBO2(i,bx2,by)].type == cBRIDGE && _effectflag_layer(bx2,by,1, &(tmpscr2[i]))) found2 = false;
18227 }
18228 }
18229 3776 }
18230
18231
18232 // Layers
18233
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1888 times.
1888 if(!(found1 || found2))
18234 {
18235 1888 foundlayer = -1;
18236
2/2
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 3776 times.
5664 for(int32_t i=0; i<2; i++)
18237 {
18238 3776 cid1 = MAPCOMBO2(i, bx, by);
18239 3776 cid2 = MAPCOMBO2(i, bx2, by);
18240 3776 newcombo const& cmb = combobuf[cid1];
18241 3776 newcombo const& cmb2 = combobuf[cid2];
18242
2/2
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 1888 times.
3776 if (i == 0)
18243 {
18244
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(tmpscr2[1].valid!=0)
18245 {
18246 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
18247 {
18248 if (combobuf[cid1].type == cBRIDGE && !_walkflag_layer(bx,by,1, &(tmpscr2[1]))) continue; //Continue, because It didn't find any on layer 0, and if you're checking
18249 if (combobuf[cid2].type == cBRIDGE && !_walkflag_layer(bx2,by,1, &(tmpscr2[1]))) continue; //layer 1 and there's a bridge on layer 2, stop checking layer 1.
18250 }
18251 else
18252 {
18253 if (combobuf[cid1].type == cBRIDGE && _effectflag_layer(bx,by,1, &(tmpscr2[1]))) continue;
18254 if (combobuf[cid2].type == cBRIDGE && _effectflag_layer(bx2,by,1, &(tmpscr2[1]))) continue;
18255 }
18256 }
18257 1888 }
18258
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3776 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3776 if(cmb.type==cLOCKBLOCK && !(cmb.triggerflags[0] & combotriggerONLYGENTRIG) && _effectflag(bx,by,1, i))
18259 {
18260 found1=true;
18261 foundlayer = i+1;
18262 //zprint("Found layer: %d \n", i);
18263 break;
18264 }
18265
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3776 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3776 else if(cmb2.type==cLOCKBLOCK && !(cmb2.triggerflags[0] & combotriggerONLYGENTRIG) && _effectflag(bx2,by,1, i))
18266 {
18267 found2=true;
18268 foundlayer = i+1;
18269 //zprint("Found layer: %d \n", i);
18270 break;
18271 }
18272 3776 }
18273 1888 }
18274
18275
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
1888 if(!(found1 || found2) || pushing<8)
18276 {
18277 1888 return;
18278 }
18279 newcombo const& cmb3 = combobuf[found1 ? cid1 : cid2];
18280 if(!try_locked_combo(cmb3))
18281 return;
18282
18283 if(cmb.usrflags&cflag16)
18284 {
18285 setxmapflag(1<<cmb.attribytes[5]);
18286 remove_xstatecombos((currscr>=128)?1:0, 1<<cmb.attribytes[5]);
18287 }
18288 else
18289 {
18290 setmapflag(mLOCKBLOCK);
18291 remove_lockblocks((currscr>=128)?1:0);
18292 }
18293 if ( cmb3.usrflags&cflag3 )
18294 {
18295 if ( (cmb3.attribytes[3]) )
18296 sfx(cmb3.attribytes[3]);
18297 }
18298 else sfx(WAV_DOOR);
18299 1888 }
18300
18301 1888 void HeroClass::oldcheckbosslockblock()
18302 {
18303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(toogam) return;
18304
18305 1888 int32_t bx = x.getInt()&0xF0;
18306 1888 int32_t bx2 = int32_t(x+8)&0xF0;
18307 1888 int32_t by = y.getInt()&0xF0;
18308
18309
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 595 times.
✓ Branch 2 taken 173 times.
✓ Branch 3 taken 399 times.
✓ Branch 4 taken 721 times.
1888 switch(dir)
18310 {
18311 case up:
18312
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 569 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 25 times.
595 if(!((int32_t)y&15)&&y!=0) by-=bigHitbox ? 16 : 0;
18313
18314 595 break;
18315
18316 case down:
18317 173 by+=16;
18318 173 break;
18319
18320 case left:
18321
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 270 times.
399 if((((int32_t)x)&0x0F)<8)
18322 270 bx-=16;
18323
18324
2/2
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 99 times.
399 if(y.getInt()&8)
18325 {
18326 99 by+=16;
18327 99 }
18328
18329 399 bx2=bx;
18330 399 break;
18331
18332 case right:
18333 721 bx+=16;
18334
18335
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 209 times.
721 if(y.getInt()&8)
18336 {
18337 209 by+=16;
18338 209 }
18339
18340 721 bx2=bx;
18341 721 break;
18342 }
18343
18344
18345 1888 bool found1 = false;
18346 1888 bool found2 = false;
18347 1888 int32_t foundlayer = -1;
18348 1888 int32_t cid1 = MAPCOMBO(bx, by), cid2 = MAPCOMBO(bx2, by);
18349 1888 newcombo const& cmb = combobuf[cid1];
18350 1888 newcombo const& cmb2 = combobuf[cid2];
18351 // Layer 0 is overridden by Locked Doors
18352
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1888 if ((cmb.type == cBOSSLOCKBLOCK && !(cmb.triggerflags[0] & combotriggerONLYGENTRIG) && _effectflag(bx, by, 1, -1) && !islockeddoor(bx, by, dLOCKED)))
18353 {
18354 found1 = true;
18355 foundlayer = 0;
18356 }
18357
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1888 else if (cmb2.type == cBOSSLOCKBLOCK && !(cmb2.triggerflags[0] & combotriggerONLYGENTRIG) && _effectflag(bx2, by, 1, -1) && !islockeddoor(bx2, by, dLOCKED))
18358 {
18359 found2 = true;
18360 foundlayer = 0;
18361 }
18362
18363
2/2
✓ Branch 0 taken 3776 times.
✓ Branch 1 taken 1888 times.
5664 for (int32_t i = 0; i <= 1; ++i)
18364 {
18365
1/2
✓ Branch 0 taken 3776 times.
✗ Branch 1 not taken.
3776 if (tmpscr2[i].valid != 0)
18366 {
18367 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
18368 {
18369 if (combobuf[MAPCOMBO2(i, bx, by)].type == cBRIDGE && !_walkflag_layer(bx, by, 1, &(tmpscr2[i]))) found1 = false;
18370 if (combobuf[MAPCOMBO2(i, bx2, by)].type == cBRIDGE && !_walkflag_layer(bx2, by, 1, &(tmpscr2[i]))) found2 = false;
18371 }
18372 else
18373 {
18374 if (combobuf[MAPCOMBO2(i, bx, by)].type == cBRIDGE && _effectflag_layer(bx, by, 1, &(tmpscr2[i]))) found1 = false;
18375 if (combobuf[MAPCOMBO2(i, bx2, by)].type == cBRIDGE && _effectflag_layer(bx2, by, 1, &(tmpscr2[i]))) found2 = false;
18376 }
18377 }
18378 3776 }
18379
18380
18381 // Layers
18382
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1888 times.
1888 if (!(found1 || found2))
18383 {
18384 1888 foundlayer = -1;
18385
2/2
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 3776 times.
5664 for (int32_t i = 0; i < 2; i++)
18386 {
18387 3776 cid1 = MAPCOMBO2(i, bx, by);
18388 3776 cid2 = MAPCOMBO2(i, bx2, by);
18389 3776 newcombo const& cmb = combobuf[cid1];
18390 3776 newcombo const& cmb2 = combobuf[cid2];
18391
2/2
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 1888 times.
3776 if (i == 0)
18392 {
18393
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if (tmpscr2[1].valid != 0)
18394 {
18395 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
18396 {
18397 if (combobuf[cid1].type == cBRIDGE && !_walkflag_layer(bx, by, 1, &(tmpscr2[1]))) continue;
18398 if (combobuf[cid2].type == cBRIDGE && !_walkflag_layer(bx2, by, 1, &(tmpscr2[1]))) continue;
18399 }
18400 else
18401 {
18402 if (combobuf[cid1].type == cBRIDGE && _effectflag_layer(bx, by, 1, &(tmpscr2[1]))) continue;
18403 if (combobuf[cid2].type == cBRIDGE && _effectflag_layer(bx2, by, 1, &(tmpscr2[1]))) continue;
18404 }
18405 }
18406 1888 }
18407
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3776 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3776 if (cmb.type == cBOSSLOCKBLOCK && !(cmb.triggerflags[0] & combotriggerONLYGENTRIG) && _effectflag(bx, by, 1, i))
18408 {
18409 found1 = true;
18410 foundlayer = i;
18411 break;
18412 }
18413
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3776 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3776 else if (cmb2.type == cBOSSLOCKBLOCK && !(cmb2.triggerflags[0] & combotriggerONLYGENTRIG) && _effectflag(bx2, by, 1, i))
18414 {
18415 found2 = true;
18416 foundlayer = i;
18417 break;
18418 }
18419 3776 }
18420 1888 }
18421
18422
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
1888 if (!(found1 || found2) || pushing < 8)
18423 {
18424 1888 return;
18425 }
18426 int32_t cid = found1 ? cid1 : cid2;
18427
18428 if(!(game->lvlitems[dlevel]&liBOSSKEY)) return;
18429
18430
18431 // Run Boss Key Script
18432 int32_t key_item = 0; //current_item_id(itype_bosskey); //not possible
18433 for ( int32_t q = 0; q < MAXITEMS; ++q )
18434 {
18435 if ( itemsbuf[q].family == itype_bosskey )
18436 {
18437 key_item = q; break;
18438 }
18439 }
18440 if ( key_item > 0 && itemsbuf[key_item].script && !(item_doscript[key_item] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) )
18441 {
18442 ri = &(itemScriptData[key_item]);
18443 for ( int32_t q = 0; q < 1024; q++ ) item_stack[key_item][q] = 0xFFFF;
18444 ri->Clear();
18445 item_doscript[key_item] = 1;
18446 itemscriptInitialised[key_item] = 0;
18447 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[key_item].script, key_item);
18448 FFCore.deallocateAllArrays(SCRIPT_ITEM,(key_item));
18449 }
18450
18451 if(cmb.usrflags&cflag16)
18452 {
18453 setxmapflag(1<<cmb.attribytes[5]);
18454 remove_xstatecombos((currscr>=128)?1:0, 1<<cmb.attribytes[5]);
18455 }
18456 else
18457 {
18458 setmapflag(mBOSSLOCKBLOCK);
18459 remove_bosslockblocks((currscr>=128)?1:0);
18460 }
18461 if ( (combobuf[cid].attribytes[3]) )
18462 sfx(combobuf[cid].attribytes[3]);
18463 1888 }
18464
18465 5664 void HeroClass::oldcheckchest(int32_t type)
18466 {
18467 // chests aren't affected by tmpscr->flags2&fAIRCOMBOS
18468
3/6
✓ Branch 0 taken 5664 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5664 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5664 times.
5664 if(toogam || z>0 || fakez > 0) return;
18469
2/2
✓ Branch 0 taken 5589 times.
✓ Branch 1 taken 75 times.
5664 if(pushing<8) return;
18470 75 int32_t bx = x.getInt()&0xF0;
18471 75 int32_t bx2 = int32_t(x+8)&0xF0;
18472 75 int32_t by = y.getInt()&0xF0;
18473
18474
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 57 times.
75 switch(dir)
18475 {
18476 case up:
18477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if(isSideViewHero()) return;
18478
18479
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
57 if(!((int32_t)y&15)&&y!=0) by-=bigHitbox ? 16 : 0;
18480
18481 57 break;
18482
18483 case left:
18484 case right:
18485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if(isSideViewHero()) break;
18486 [[fallthrough]];
18487 case down:
18488 18 return;
18489 }
18490
18491 57 bool found=false;
18492 57 bool itemflag=false;
18493
18494
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
57 if((combobuf[MAPCOMBO(bx,by)].type==type && _effectflag(bx,by,1, -1))||
18495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 (combobuf[MAPCOMBO(bx2,by)].type==type && _effectflag(bx2,by,1, -1)))
18496 {
18497 found=true;
18498 }
18499
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 57 times.
171 for (int32_t i = 0; i <= 1; ++i)
18500 {
18501
1/2
✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
114 if(tmpscr2[i].valid!=0)
18502 {
18503 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
18504 {
18505 if (combobuf[MAPCOMBO2(i,bx,by)].type == cBRIDGE && !_walkflag_layer(bx,by,1, &(tmpscr2[i]))) found = false;
18506 if (combobuf[MAPCOMBO2(i,bx2,by)].type == cBRIDGE && !_walkflag_layer(bx2,by,1, &(tmpscr2[i]))) found = false;
18507 }
18508 else
18509 {
18510 if (combobuf[MAPCOMBO2(i,bx,by)].type == cBRIDGE && _effectflag_layer(bx,by,1, &(tmpscr2[i]))) found = false;
18511 if (combobuf[MAPCOMBO2(i,bx2,by)].type == cBRIDGE && _effectflag_layer(bx2,by,1, &(tmpscr2[i]))) found = false;
18512 }
18513 }
18514 114 }
18515
18516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if(!found)
18517 {
18518
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 114 times.
171 for(int32_t i=0; i<2; i++)
18519 {
18520
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 57 times.
114 if (i == 0)
18521 {
18522
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if(tmpscr2[1].valid!=0)
18523 {
18524 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
18525 {
18526 if (combobuf[MAPCOMBO2(1,bx,by)].type == cBRIDGE && !_walkflag_layer(bx,by,1, &(tmpscr2[1]))) continue;
18527 if (combobuf[MAPCOMBO2(1,bx2,by)].type == cBRIDGE && !_walkflag_layer(bx2,by,1, &(tmpscr2[1]))) continue;
18528 }
18529 else
18530 {
18531 if (combobuf[MAPCOMBO2(1,bx,by)].type == cBRIDGE && _effectflag_layer(bx,by,1, &(tmpscr2[1]))) continue;
18532 if (combobuf[MAPCOMBO2(1,bx2,by)].type == cBRIDGE && _effectflag_layer(bx2,by,1, &(tmpscr2[1]))) continue;
18533 }
18534 }
18535 57 }
18536
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
114 if((combobuf[MAPCOMBO2(i,bx,by)].type==type && _effectflag(bx,by,1, i))||
18537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 (combobuf[MAPCOMBO2(i,bx2,by)].type==type && _effectflag(bx2,by,1, i)))
18538 {
18539 found=true;
18540 break;
18541 }
18542 114 }
18543 57 }
18544
18545
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if(!found)
18546 {
18547 57 return;
18548 }
18549
18550 switch(type)
18551 {
18552 case cLOCKEDCHEST:
18553 if(!usekey()) return;
18554
18555 setmapflag(mLOCKEDCHEST);
18556 break;
18557
18558 case cCHEST:
18559 setmapflag(mCHEST);
18560 break;
18561
18562 case cBOSSCHEST:
18563 if(!(game->lvlitems[dlevel]&liBOSSKEY)) return;
18564 // Run Boss Key Script
18565 int32_t key_item = 0; //current_item_id(itype_bosskey); //not possible
18566 for ( int32_t q = 0; q < MAXITEMS; ++q )
18567 {
18568 if ( itemsbuf[q].family == itype_bosskey )
18569 {
18570 key_item = q; break;
18571 }
18572 }
18573 if ( key_item > 0 && itemsbuf[key_item].script && !(item_doscript[key_item] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) )
18574 {
18575 ri = &(itemScriptData[key_item]);
18576 for ( int32_t q = 0; q < 1024; q++ ) item_stack[key_item][q] = 0xFFFF;
18577 ri->Clear();
18578 item_doscript[key_item] = 1;
18579 itemscriptInitialised[key_item] = 0;
18580 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[key_item].script, key_item);
18581 FFCore.deallocateAllArrays(SCRIPT_ITEM,(key_item));
18582 }
18583 setmapflag(mBOSSCHEST);
18584 break;
18585 }
18586
18587 itemflag |= MAPCOMBOFLAG(bx,by)==mfARMOS_ITEM;
18588 itemflag |= MAPCOMBOFLAG(bx2,by)==mfARMOS_ITEM;
18589 itemflag |= MAPFLAG(bx,by)==mfARMOS_ITEM;
18590 itemflag |= MAPFLAG(bx2,by)==mfARMOS_ITEM;
18591 itemflag |= MAPCOMBOFLAG(bx,by)==mfARMOS_ITEM;
18592 itemflag |= MAPCOMBOFLAG(bx2,by)==mfARMOS_ITEM;
18593
18594 if(!itemflag)
18595 {
18596 for(int32_t i=0; i<2; i++)
18597 {
18598 itemflag |= MAPFLAG2(i,bx,by)==mfARMOS_ITEM;
18599 itemflag |= MAPFLAG2(i,bx2,by)==mfARMOS_ITEM;
18600 itemflag |= MAPCOMBOFLAG2(i,bx,by)==mfARMOS_ITEM;
18601 itemflag |= MAPCOMBOFLAG2(i,bx2,by)==mfARMOS_ITEM;
18602 }
18603 }
18604
18605 if(itemflag && !getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM))
18606 {
18607 items.add(new item(x, y,(zfix)0, tmpscr->catchall, ipONETIME2 + ipBIGRANGE + ipHOLDUP | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0), 0));
18608 }
18609 5664 }
18610
18611 void HeroClass::checkchest(int32_t type)
18612 {
18613 bool ischest = type == cCHEST || type == cLOCKEDCHEST || type == cBOSSCHEST;
18614 bool islockblock = type == cLOCKBLOCK || type == cBOSSLOCKBLOCK;
18615 bool islocked = type == cLOCKBLOCK || type == cLOCKEDCHEST;
18616 bool isbosslocked = type == cBOSSLOCKBLOCK || type == cBOSSCHEST;
18617 if(ischest)
18618 {
18619 if(get_bit(quest_rules,qr_OLD_CHEST_COLLISION))
18620 {
18621 oldcheckchest(type);
18622 return;
18623 }
18624 }
18625 if(islockblock && get_bit(quest_rules, qr_OLD_LOCKBLOCK_COLLISION))
18626 {
18627 if(type == cLOCKBLOCK)
18628 oldchecklockblock();
18629 else if(type == cBOSSLOCKBLOCK)
18630 oldcheckbosslockblock();
18631 return;
18632 }
18633 if(toogam || z>0 || fakez > 0) return;
18634 zfix bx, by;
18635 zfix bx2, by2;
18636 zfix fx(-1), fy(-1);
18637 switch(dir)
18638 {
18639 case up:
18640 by = y + (bigHitbox ? -2 : 6);
18641 by2 = by;
18642 bx = x + 4;
18643 bx2 = bx + 8;
18644 break;
18645 case down:
18646 by = y + 17;
18647 by2 = by;
18648 bx = x + 4;
18649 bx2 = bx + 8;
18650 break;
18651 case left:
18652 by = y + (bigHitbox ? 0 : 8);
18653 by2 = y + 8;
18654 bx = x - 2;
18655 bx2 = x - 2;
18656 break;
18657 case right:
18658 by = y + (bigHitbox ? 0 : 8);
18659 by2 = y + 8;
18660 bx = x + 17;
18661 bx2 = x + 17;
18662 break;
18663 }
18664
18665 int32_t found = -1;
18666 int32_t foundlayer = 0;
18667
18668 newcombo const* cmb = &combobuf[MAPCOMBO(bx,by)];
18669
18670 if(cmb->type==type && !(cmb->triggerflags[0] & combotriggerONLYGENTRIG) && _effectflag(bx,by,1, -1))
18671 {
18672 found = MAPCOMBO(bx,by);
18673 fx = bx; fy = by;
18674 for (int32_t i = 0; i <= 1; ++i)
18675 {
18676 if(tmpscr2[i].valid!=0)
18677 {
18678 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
18679 {
18680 if (combobuf[MAPCOMBO2(i,bx,by)].type == cBRIDGE && !_walkflag_layer(bx,by,1, &(tmpscr2[i]))) found = -1;
18681 }
18682 else
18683 {
18684 if (combobuf[MAPCOMBO2(i,bx,by)].type == cBRIDGE && _effectflag_layer(bx,by,1, &(tmpscr2[i]))) found = -1;
18685 }
18686 }
18687 }
18688 }
18689 if(found<0)
18690 {
18691 cmb = &combobuf[MAPCOMBO(bx2,by2)];
18692 if(cmb->type==type && !(cmb->triggerflags[0] & combotriggerONLYGENTRIG) && _effectflag(bx2,by2,1, -1))
18693 {
18694 found = MAPCOMBO(bx2,by2);
18695 for (int32_t i = 0; i <= 6; ++i)
18696 {
18697 if(tmpscr2[i].valid!=0)
18698 {
18699 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
18700 {
18701 if (combobuf[MAPCOMBO2(i,bx2,by2)].type == cBRIDGE && !_walkflag_layer(bx2,by2,1, &(tmpscr2[i])))
18702 {
18703 found = -1;
18704 break;
18705 }
18706 }
18707 else
18708 {
18709 if (combobuf[MAPCOMBO2(i,bx2,by2)].type == cBRIDGE && _effectflag_layer(bx2,by2,1, &(tmpscr2[i])))
18710 {
18711 found = -1;
18712 break;
18713 }
18714 }
18715 }
18716 }
18717 if(found != -1)
18718 {
18719 fx = bx2; fy = by2;
18720 }
18721 }
18722 }
18723
18724 if(found<0)
18725 {
18726 for(int32_t i=0; i<6; i++)
18727 {
18728 cmb = &combobuf[MAPCOMBO2(i,bx,by)];
18729 if(combobuf[MAPCOMBO2(i,bx,by)].type==type && !(cmb->triggerflags[0] & combotriggerONLYGENTRIG) && _effectflag(bx,by,1, i))
18730 {
18731 found = MAPCOMBO2(i,bx,by);
18732 for(int32_t j = i+1; j < 6; ++j)
18733 {
18734 if (tmpscr2[j].valid!=0)
18735 {
18736 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
18737 {
18738 if (combobuf[MAPCOMBO2(j,bx,by)].type == cBRIDGE && !_walkflag_layer(bx,by,1, &(tmpscr2[j])))
18739 {
18740 found = -1;
18741 break;
18742 }
18743 }
18744 else
18745 {
18746 if (combobuf[MAPCOMBO2(j,bx,by)].type == cBRIDGE && _effectflag_layer(bx,by,1, &(tmpscr2[j])))
18747 {
18748 found = -1;
18749 break;
18750 }
18751 }
18752 }
18753 }
18754 if(found>-1)
18755 {
18756 foundlayer = i+1;
18757 fx = bx; fy = by;
18758 break;
18759 }
18760 }
18761 cmb = &combobuf[MAPCOMBO2(i,bx2,by2)];
18762 if(combobuf[MAPCOMBO2(i,bx2,by2)].type==type && !(cmb->triggerflags[0] & combotriggerONLYGENTRIG) && _effectflag(bx2,by2,1, i))
18763 {
18764 found = MAPCOMBO2(i,bx2,by2);
18765 for(int32_t j = i+1; j < 6; ++j)
18766 {
18767 if (tmpscr2[j].valid!=0)
18768 {
18769 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
18770 {
18771 if (combobuf[MAPCOMBO2(j,bx2,by2)].type == cBRIDGE && !_walkflag_layer(bx2,by2,1, &(tmpscr2[j])))
18772 {
18773 found = -1;
18774 break;
18775 }
18776 }
18777 else
18778 {
18779 if (combobuf[MAPCOMBO2(j,bx2,by2)].type == cBRIDGE && _effectflag_layer(bx2,by2,1, &(tmpscr2[j])))
18780 {
18781 found = -1;
18782 break;
18783 }
18784 }
18785 }
18786 }
18787 if(found>-1)
18788 {
18789 foundlayer = i+1;
18790 fx = bx2; fy = by2;
18791 break;
18792 }
18793 }
18794 }
18795 }
18796
18797 if(found<0) return;
18798 cmb = &combobuf[found];
18799 switch(dir)
18800 {
18801 case up:
18802 if(cmb->usrflags&cflag10)
18803 return;
18804 break;
18805 case down:
18806 if(cmb->usrflags&cflag9)
18807 return;
18808 break;
18809 case left:
18810 if(cmb->usrflags&cflag12)
18811 return;
18812 break;
18813 case right:
18814 if(cmb->usrflags&cflag11)
18815 return;
18816 break;
18817 }
18818 int32_t intbtn = cmb->attribytes[2];
18819
18820 if(intbtn) //
18821 {
18822 if(cmb->usrflags & cflag13) //display prompt
18823 {
18824 int altcmb = cmb->attributes[2]/10000;
18825 prompt_combo = cmb->attributes[1]/10000;
18826 if(altcmb && ((islocked && !can_locked_combo(*cmb))
18827 || (isbosslocked && !(game->lvlitems[dlevel]&liBOSSKEY))))
18828 prompt_combo = altcmb;
18829 prompt_cset = cmb->attribytes[4];
18830 prompt_x = cmb->attrishorts[0];
18831 prompt_y = cmb->attrishorts[1];
18832 }
18833 if(!getIntBtnInput(intbtn, true, true, false, false))
18834 {
18835 return; //Button not pressed
18836 }
18837 }
18838 else if(pushing < 8) return; //Not pushing against chest enough
18839
18840 if(ischest)
18841 {
18842 if(!trigger_chest(foundlayer, COMBOPOS(fx,fy))) return;
18843 }
18844 else if(islockblock)
18845 {
18846 if(!trigger_lockblock(foundlayer, COMBOPOS(fx,fy))) return;
18847 }
18848 if(intbtn && (cmb->usrflags & cflag13))
18849 prompt_combo = 0;
18850 }
18851
18852 1888 void HeroClass::checkgenpush()
18853 {
18854
4/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 1863 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 21 times.
1888 if(pushing < 8 || pushing % 8) return;
18855 4 zfix bx, by;
18856 4 zfix bx2, by2;
18857
2/5
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
4 switch(dir)
18858 {
18859 case up:
18860 3 by = y + (bigHitbox ? -2 : 6);
18861 3 by2 = by;
18862 3 bx = x + 4;
18863 3 bx2 = bx + 8;
18864 3 break;
18865 case down:
18866 by = y + 17;
18867 by2 = by;
18868 bx = x + 4;
18869 bx2 = bx + 8;
18870 break;
18871 case left:
18872 1 by = y + (bigHitbox ? 0 : 8);
18873 1 by2 = y + 8;
18874 1 bx = x - 2;
18875 1 bx2 = x - 2;
18876 1 break;
18877 case right:
18878 by = y + (bigHitbox ? 0 : 8);
18879 by2 = y + 8;
18880 bx = x + 17;
18881 bx2 = x + 17;
18882 break;
18883 }
18884 4 auto pos1 = COMBOPOS(bx,by);
18885 4 auto pos2 = COMBOPOS(bx2,by2);
18886
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 28 times.
32 for(auto layer = 0; layer < 7; ++layer)
18887 {
18888 28 mapscr* tmp = FFCore.tempScreens[layer];
18889
18890 28 newcombo const& cmb1 = combobuf[tmp->data[pos1]];
18891
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if(cmb1.triggerflags[1] & combotriggerPUSH)
18892 do_trigger_combo(layer,pos1);
18893
18894
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if(pos1==pos2) continue;
18895
18896 newcombo const& cmb2 = combobuf[tmp->data[pos2]];
18897 if(cmb2.triggerflags[1] & combotriggerPUSH)
18898 do_trigger_combo(layer,pos2);
18899 }
18900 1888 }
18901
18902 1888 void HeroClass::checksigns() //Also checks for generic trigger buttons
18903 {
18904
3/6
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1888 times.
1888 if(toogam || z>0 || fakez>0) return;
18905
5/6
✓ Branch 0 taken 1666 times.
✓ Branch 1 taken 222 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 1612 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 54 times.
1888 if(msg_active || (msg_onscreen && get_bit(quest_rules, qr_MSGDISAPPEAR)))
18906 222 return; //Don't overwrite a message waiting to be dismissed
18907 1666 zfix bx, by;
18908 1666 zfix bx2, by2;
18909 1666 zfix fx(-1), fy(-1);
18910
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 376 times.
✓ Branch 2 taken 173 times.
✓ Branch 3 taken 399 times.
✓ Branch 4 taken 718 times.
1666 switch(dir)
18911 {
18912 case up:
18913 376 by = y + (bigHitbox ? -2 : 6);
18914 376 by2 = by;
18915 376 bx = x + 4;
18916 376 bx2 = bx + 8;
18917 376 break;
18918 case down:
18919 173 by = y + 17;
18920 173 by2 = by;
18921 173 bx = x + 4;
18922 173 bx2 = bx + 8;
18923 173 break;
18924 case left:
18925 399 by = y + (bigHitbox ? 0 : 8);
18926 399 by2 = y + 8;
18927 399 bx = x - 2;
18928 399 bx2 = x - 2;
18929 399 break;
18930 case right:
18931 718 by = y + (bigHitbox ? 0 : 8);
18932 718 by2 = y + 8;
18933 718 bx = x + 17;
18934 718 bx2 = x + 17;
18935 718 break;
18936 }
18937
18938 1666 int32_t found = -1;
18939 1666 int32_t found_lyr = 0;
18940 1666 bool found_sign = false;
18941 1666 int32_t tmp_cid = MAPCOMBO(bx,by);
18942 1666 newcombo const* tmp_cmb = &combobuf[tmp_cid];
18943
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1666 times.
✓ Branch 2 taken 1666 times.
✗ Branch 3 not taken.
3332 if(((tmp_cmb->type==cSIGNPOST && !(tmp_cmb->triggerflags[0] & combotriggerONLYGENTRIG))
18944 1666 || tmp_cmb->triggerbtn) && _effectflag(bx,by,1, -1))
18945 {
18946 found = tmp_cid;
18947 fx = bx; fy = by;
18948 for (int32_t i = 0; i <= 1; ++i)
18949 {
18950 if(tmpscr2[i].valid!=0)
18951 {
18952 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
18953 {
18954 if (combobuf[MAPCOMBO2(i,bx,by)].type == cBRIDGE && !_walkflag_layer(bx,by,1, &(tmpscr2[i]))) found = -1;
18955 }
18956 else
18957 {
18958 if (combobuf[MAPCOMBO2(i,bx,by)].type == cBRIDGE && _effectflag_layer(bx,by,1, &(tmpscr2[i]))) found = -1;
18959 }
18960 }
18961 }
18962 }
18963 1666 tmp_cid = MAPCOMBO(bx2,by2);
18964 1666 tmp_cmb = &combobuf[tmp_cid];
18965
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1666 times.
✓ Branch 2 taken 1666 times.
✗ Branch 3 not taken.
3332 if(((tmp_cmb->type==cSIGNPOST && !(tmp_cmb->triggerflags[0] & combotriggerONLYGENTRIG))
18966 1666 || tmp_cmb->triggerbtn) && _effectflag(bx2,by2,1, -1))
18967 {
18968 found = tmp_cid;
18969 fx = bx2; fy = by2;
18970 for (int32_t i = 0; i <= 1; ++i)
18971 {
18972 if(tmpscr2[i].valid!=0)
18973 {
18974 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
18975 {
18976 if (combobuf[MAPCOMBO2(i,bx2,by2)].type == cBRIDGE && !_walkflag_layer(bx2,by2,1, &(tmpscr2[i]))) found = -1;
18977 }
18978 else
18979 {
18980 if (combobuf[MAPCOMBO2(i,bx2,by2)].type == cBRIDGE && _effectflag_layer(bx2,by2,1, &(tmpscr2[i]))) found = -1;
18981 }
18982 }
18983 }
18984 }
18985
18986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1666 times.
1666 if(found<0)
18987 {
18988
2/2
✓ Branch 0 taken 1666 times.
✓ Branch 1 taken 9996 times.
11662 for(int32_t i=0; i<6; i++)
18989 {
18990 9996 tmp_cid = MAPCOMBO2(i,bx,by);
18991 9996 tmp_cmb = &combobuf[tmp_cid];
18992
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9996 times.
✓ Branch 2 taken 9996 times.
✗ Branch 3 not taken.
19992 if(((tmp_cmb->type==cSIGNPOST && !(tmp_cmb->triggerflags[0] & combotriggerONLYGENTRIG))
18993 9996 || tmp_cmb->triggerbtn) && _effectflag(bx,by,1, i))
18994 {
18995 found = tmp_cid;
18996 found_lyr = i+1;
18997 fx = bx; fy = by;
18998 if (i == 0 && tmpscr2[1].valid!=0)
18999 {
19000 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
19001 {
19002 if (combobuf[MAPCOMBO2(1,bx,by)].type == cBRIDGE && !_walkflag_layer(bx,by,1, &(tmpscr2[1]))) found = -1;
19003 }
19004 else
19005 {
19006 if (combobuf[MAPCOMBO2(1,bx,by)].type == cBRIDGE && _effectflag_layer(bx,by,1, &(tmpscr2[1]))) found = -1;
19007 }
19008 }
19009 }
19010 9996 tmp_cid = MAPCOMBO2(i,bx2,by2);
19011 9996 tmp_cmb = &combobuf[tmp_cid];
19012
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9996 times.
✓ Branch 2 taken 9996 times.
✗ Branch 3 not taken.
19992 if(((tmp_cmb->type==cSIGNPOST && !(tmp_cmb->triggerflags[0] & combotriggerONLYGENTRIG))
19013 9996 || tmp_cmb->triggerbtn) && _effectflag(bx2,by2,1, i))
19014 {
19015 found = tmp_cid;
19016 found_lyr = i+1;
19017 fx = bx2; fy = by2;
19018 if (i == 0 && tmpscr2[1].valid!=0)
19019 {
19020 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
19021 {
19022 if (combobuf[MAPCOMBO2(1,bx2,by2)].type == cBRIDGE && !_walkflag_layer(bx2,by2,1, &(tmpscr2[1]))) found = -1;
19023 }
19024 else
19025 {
19026 if (combobuf[MAPCOMBO2(1,bx2,by2)].type == cBRIDGE && _effectflag_layer(bx2,by2,1, &(tmpscr2[1]))) found = -1;
19027 }
19028 }
19029 }
19030
1/2
✓ Branch 0 taken 9996 times.
✗ Branch 1 not taken.
9996 if(found>-1) break;
19031 9996 }
19032 1666 }
19033
19034
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1666 times.
1666 if(found<0) return;
19035 newcombo const& cmb = combobuf[found];
19036
19037 byte signInput = 0;
19038 bool didsign = false;
19039 if(cmb.type == cSIGNPOST && !(cmb.triggerflags[0] & combotriggerONLYGENTRIG))
19040 {
19041 switch(dir)
19042 {
19043 case up:
19044 if(cmb.usrflags&cflag10)
19045 goto endsigns;
19046 break;
19047 case down:
19048 if(cmb.usrflags&cflag9)
19049 goto endsigns;
19050 break;
19051 case left:
19052 if(cmb.usrflags&cflag12)
19053 goto endsigns;
19054 break;
19055 case right:
19056 if(cmb.usrflags&cflag11)
19057 goto endsigns;
19058 break;
19059 }
19060 int32_t intbtn = cmb.attribytes[2];
19061
19062 if(intbtn) //
19063 {
19064 signInput = getIntBtnInput(intbtn, true, true, false, false);
19065 if(!signInput)
19066 {
19067 if(cmb.usrflags & cflag13) //display prompt
19068 {
19069 prompt_combo = cmb.attributes[1]/10000;
19070 prompt_cset = cmb.attribytes[4];
19071 prompt_x = cmb.attrishorts[0];
19072 prompt_y = cmb.attrishorts[1];
19073 }
19074 goto endsigns; //Button not pressed
19075 }
19076 }
19077 else if(pushing < 8 || pushing%8) goto endsigns; //Not pushing against sign enough
19078
19079 trigger_sign(cmb);
19080 didsign = true;
19081 }
19082 endsigns:
19083 if(!cmb.triggerbtn) return;
19084 if(on_cooldown(found_lyr, COMBOPOS(fx,fy))) return;
19085 switch(dir)
19086 {
19087 case down:
19088 if(!(cmb.triggerflags[0] & combotriggerBTN_TOP))
19089 return;
19090 break;
19091 case up:
19092 if(!(cmb.triggerflags[0] & combotriggerBTN_BOTTOM))
19093 return;
19094 break;
19095 case right:
19096 if(!(cmb.triggerflags[0] & combotriggerBTN_LEFT))
19097 return;
19098 break;
19099 case left:
19100 if(!(cmb.triggerflags[0] & combotriggerBTN_RIGHT))
19101 return;
19102 break;
19103 }
19104 if(getIntBtnInput(cmb.triggerbtn, true, true, false, false) || checkIntBtnVal(cmb.triggerbtn, signInput))
19105 do_trigger_combo(found_lyr, COMBOPOS(fx,fy), didsign ? ctrigIGNORE_SIGN : 0);
19106 else if(cmb.type == cBUTTONPROMPT)
19107 {
19108 prompt_combo = cmb.attributes[0]/10000;
19109 prompt_cset = cmb.attribytes[0];
19110 prompt_x = cmb.attrishorts[0];
19111 prompt_y = cmb.attrishorts[1];
19112 }
19113 else if(cmb.prompt_cid)
19114 {
19115 prompt_combo = cmb.prompt_cid;
19116 prompt_cset = cmb.prompt_cs;
19117 prompt_x = cmb.prompt_x;
19118 prompt_y = cmb.prompt_y;
19119 }
19120 1888 }
19121
19122 1888 void HeroClass::checklocked()
19123 {
19124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(toogam) return; //Walk through walls.
19125
19126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(!isdungeon()) return;
19127
19128 if( !diagonalMovement && pushing!=8) return;
19129 /*This is required to allow the player to open a door, while sliding along a wall (pressing in the direction of the door, and sliding left or right)
19130 */
19131 if ( diagonalMovement && pushing < 8 ) return; //Allow wall walking Should I add a quest rule for this? -Z
19132
19133
19134 bool found = false;
19135 for ( int32_t q = 0; q < 4; q++ ) {
19136 if ( tmpscr->door[q] == dLOCKED || tmpscr->door[q] == dBOSS ) { found = true; }
19137 }
19138
19139 if ( !found ) return;
19140
19141 int32_t si = (currmap<<7) + currscr;
19142 int32_t di = 0;
19143
19144
19145
19146 if ( diagonalMovement || get_bit(quest_rules, qr_DISABLE_4WAY_GRIDLOCK))
19147 {
19148 //Up door
19149 if ( y <= 32 && x >= 112 && x <= 128 )
19150 {
19151 if (
19152 dir == up || dir == l_up || dir == r_up //|| Up() || ( Up()&&Left()) || ( Up()&&Right())
19153
19154 )
19155 {
19156 di = nextscr(up);
19157 if(tmpscr->door[0]==dLOCKED)
19158 {
19159 if(usekey())
19160 {
19161 putdoor(scrollbuf,0,up,dUNLOCKED);
19162 tmpscr->door[0]=dUNLOCKED;
19163 setmapflag(si, mDOOR_UP);
19164
19165 if(di != 0xFFFF)
19166 setmapflag(di, mDOOR_DOWN);
19167 sfx(WAV_DOOR);
19168 markBmap(-1);
19169 }
19170 else return;
19171 }
19172 else if(tmpscr->door[0]==dBOSS)
19173 {
19174 if(game->lvlitems[dlevel]&liBOSSKEY)
19175 {
19176 putdoor(scrollbuf,0,up,dOPENBOSS);
19177 tmpscr->door[0]=dOPENBOSS;
19178 setmapflag(si, mDOOR_UP);
19179
19180 if(di != 0xFFFF)
19181 setmapflag(di, mDOOR_DOWN);
19182 sfx(WAV_DOOR);
19183 markBmap(-1);
19184 // Run Boss Key Script
19185 int32_t key_item = 0; //current_item_id(itype_bosskey); //not possible
19186 for ( int32_t q = 0; q < MAXITEMS; ++q )
19187 {
19188 if ( itemsbuf[q].family == itype_bosskey )
19189 {
19190 key_item = q; break;
19191 }
19192 }
19193 if ( key_item > 0 && itemsbuf[key_item].script && !(item_doscript[key_item] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) )
19194 {
19195 ri = &(itemScriptData[key_item]);
19196 for ( int32_t q = 0; q < 1024; q++ ) item_stack[key_item][q] = 0xFFFF;
19197 ri->Clear();
19198 item_doscript[key_item] = 1;
19199 itemscriptInitialised[key_item] = 0;
19200 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[key_item].script, key_item);
19201 FFCore.deallocateAllArrays(SCRIPT_ITEM,(key_item));
19202 }
19203 }
19204 else return;
19205
19206 }
19207
19208 }
19209 }
19210 //Down
19211 if ( y >= 128 && x >= 112 && x <= 128 )
19212 {
19213 if ( dir == down || dir == l_down || dir == r_down ) //|| Down() || ( Down()&&Left()) || ( Down()&&Right()))
19214 {
19215 di = nextscr(down);
19216 if(tmpscr->door[1]==dLOCKED)
19217 {
19218 if(usekey())
19219 {
19220 putdoor(scrollbuf,0,down,dUNLOCKED);
19221 tmpscr->door[1]=dUNLOCKED;
19222 setmapflag(si, mDOOR_DOWN);
19223
19224 if(di != 0xFFFF)
19225 setmapflag(di, mDOOR_UP);
19226 sfx(WAV_DOOR);
19227 markBmap(-1);
19228 }
19229 else return;
19230 }
19231 else if(tmpscr->door[1]==dBOSS)
19232 {
19233 if(game->lvlitems[dlevel]&liBOSSKEY)
19234 {
19235 putdoor(scrollbuf,0,down,dOPENBOSS);
19236 tmpscr->door[1]=dOPENBOSS;
19237 setmapflag(si, mDOOR_DOWN);
19238
19239 if(di != 0xFFFF)
19240 setmapflag(di, mDOOR_UP);
19241 sfx(WAV_DOOR);
19242 markBmap(-1);
19243 // Run Boss Key Script
19244 int32_t key_item = 0; //current_item_id(itype_bosskey); //not possible
19245 for ( int32_t q = 0; q < MAXITEMS; ++q )
19246 {
19247 if ( itemsbuf[q].family == itype_bosskey )
19248 {
19249 key_item = q; break;
19250 }
19251 }
19252 if ( key_item > 0 && itemsbuf[key_item].script && !(item_doscript[key_item] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) )
19253 {
19254 ri = &(itemScriptData[key_item]);
19255 for ( int32_t q = 0; q < 1024; q++ ) item_stack[key_item][q] = 0xFFFF;
19256 ri->Clear();
19257 item_doscript[key_item] = 1;
19258 itemscriptInitialised[key_item] = 0;
19259 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[key_item].script, key_item);
19260 FFCore.deallocateAllArrays(SCRIPT_ITEM,(key_item));
19261 }
19262 }
19263 else return;
19264 }
19265 }
19266 }
19267 //left
19268 if ( y > 72 && y < 88 && x <= 32 )
19269 {
19270 if ( dir == left || dir == l_up || dir == l_down )//|| Left() || ( Up()&&Left()) || ( Down()&&Left() ) )
19271 {
19272 di = nextscr(left);
19273 if(tmpscr->door[2]==dLOCKED)
19274 {
19275 if(usekey())
19276 {
19277 putdoor(scrollbuf,0,left,dUNLOCKED);
19278 tmpscr->door[2]=dUNLOCKED;
19279 setmapflag(si, mDOOR_LEFT);
19280
19281 if(di != 0xFFFF)
19282 setmapflag(di, mDOOR_RIGHT);
19283 sfx(WAV_DOOR);
19284 markBmap(-1);
19285 }
19286 else return;
19287 }
19288 else if(tmpscr->door[2]==dBOSS)
19289 {
19290 if(game->lvlitems[dlevel]&liBOSSKEY)
19291 {
19292 putdoor(scrollbuf,0,left,dOPENBOSS);
19293 tmpscr->door[2]=dOPENBOSS;
19294 setmapflag(si, mDOOR_LEFT);
19295
19296 if(di != 0xFFFF)
19297 setmapflag(di, mDOOR_RIGHT);
19298 sfx(WAV_DOOR);
19299 markBmap(-1);
19300 // Run Boss Key Script
19301 int32_t key_item = 0; //current_item_id(itype_bosskey); //not possible
19302 for ( int32_t q = 0; q < MAXITEMS; ++q )
19303 {
19304 if ( itemsbuf[q].family == itype_bosskey )
19305 {
19306 key_item = q; break;
19307 }
19308 }
19309 if ( key_item > 0 && itemsbuf[key_item].script && !(item_doscript[key_item] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) )
19310 {
19311 ri = &(itemScriptData[key_item]);
19312 for ( int32_t q = 0; q < 1024; q++ ) item_stack[key_item][q] = 0xFFFF;
19313 ri->Clear();
19314 item_doscript[key_item] = 1;
19315 itemscriptInitialised[key_item] = 0;
19316 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[key_item].script, key_item);
19317 FFCore.deallocateAllArrays(SCRIPT_ITEM,(key_item));
19318 }
19319 }
19320 else return;
19321 }
19322 }
19323 }
19324
19325
19326 //right
19327 if ( ( y > 72 && y < 88 ) && x >= 208 )
19328 //!( (y<=72||y>=88) && x<206 ) )
19329 //y<=72||y>=88):y!=80) || x<208)
19330 {
19331 if ( dir == right || dir == r_up || dir == r_down ) //|| Right() || ( Down()&&Right() ) || ( Up()&&Right()))
19332 {
19333 di = nextscr(right);
19334 if(tmpscr->door[right]==dLOCKED)
19335 {
19336 if(usekey())
19337 {
19338 putdoor(scrollbuf,0,right,dUNLOCKED);
19339 tmpscr->door[3]=dUNLOCKED;
19340 setmapflag(si, mDOOR_RIGHT);
19341
19342 if(di != 0xFFFF)
19343 setmapflag(di, mDOOR_LEFT);
19344 sfx(WAV_DOOR);
19345 markBmap(-1);
19346 }
19347 else return;
19348 }
19349 else if(tmpscr->door[right]==dBOSS)
19350 {
19351 if(game->lvlitems[dlevel]&liBOSSKEY)
19352 {
19353 putdoor(scrollbuf,0,right,dOPENBOSS);
19354 tmpscr->door[3]=dOPENBOSS;
19355 setmapflag(si, mDOOR_RIGHT);
19356
19357 if(di != 0xFFFF)
19358 setmapflag(di, mDOOR_LEFT);
19359 sfx(WAV_DOOR);
19360 markBmap(-1);
19361 // Run Boss Key Script
19362 int32_t key_item = 0; //current_item_id(itype_bosskey); //not possible
19363 for ( int32_t q = 0; q < MAXITEMS; ++q )
19364 {
19365 if ( itemsbuf[q].family == itype_bosskey )
19366 {
19367 key_item = q; break;
19368 }
19369 }
19370 if ( key_item > 0 && itemsbuf[key_item].script && !(item_doscript[key_item] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) )
19371 {
19372 ri = &(itemScriptData[key_item]);
19373 for ( int32_t q = 0; q < 1024; q++ ) item_stack[key_item][q] = 0xFFFF;
19374 ri->Clear();
19375 item_doscript[key_item] = 1;
19376 itemscriptInitialised[key_item] = 0;
19377 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[key_item].script, key_item);
19378 FFCore.deallocateAllArrays(SCRIPT_ITEM,(key_item));
19379 }
19380 }
19381 else return;
19382 }
19383
19384 }
19385 }
19386 }
19387 else
19388 {
19389 //orthogonal movement
19390 //Up door
19391 if ( y<=32 && x == 120 )
19392 //!( y>32 && (x!=120) ))
19393 {
19394 switch ( dir )
19395 {
19396 case up:
19397 case r_up:
19398 case l_up:
19399 {
19400 di = nextscr(up);
19401 if(tmpscr->door[0]==dLOCKED)
19402 {
19403 if(usekey())
19404 {
19405 putdoor(scrollbuf,0,up,dUNLOCKED);
19406 tmpscr->door[0]=dUNLOCKED;
19407 setmapflag(si, mDOOR_UP);
19408
19409 if(di != 0xFFFF)
19410 setmapflag(di, mDOOR_DOWN);
19411 sfx(WAV_DOOR);
19412 markBmap(-1);
19413 }
19414 else return;
19415 }
19416 else if(tmpscr->door[0]==dBOSS)
19417 {
19418 if(game->lvlitems[dlevel]&liBOSSKEY)
19419 {
19420 putdoor(scrollbuf,0,up,dOPENBOSS);
19421 tmpscr->door[0]=dOPENBOSS;
19422 setmapflag(si, mDOOR_UP);
19423
19424 if(di != 0xFFFF)
19425 setmapflag(di, mDOOR_DOWN);
19426 sfx(WAV_DOOR);
19427 markBmap(-1);
19428 // Run Boss Key Script
19429 int32_t key_item = 0; //current_item_id(itype_bosskey); //not possible
19430 for ( int32_t q = 0; q < MAXITEMS; ++q )
19431 {
19432 if ( itemsbuf[q].family == itype_bosskey )
19433 {
19434 key_item = q; break;
19435 }
19436 }
19437 if ( key_item > 0 && itemsbuf[key_item].script && !(item_doscript[key_item] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) )
19438 {
19439 ri = &(itemScriptData[key_item]);
19440 for ( int32_t q = 0; q < 1024; q++ ) item_stack[key_item][q] = 0xFFFF;
19441 ri->Clear();
19442 item_doscript[key_item] = 1;
19443 itemscriptInitialised[key_item] = 0;
19444 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[key_item].script, key_item);
19445 FFCore.deallocateAllArrays(SCRIPT_ITEM,(key_item));
19446 }
19447 }
19448 else return;
19449 }
19450 break;
19451 }
19452 default: break;
19453
19454 }
19455 }
19456 //Down
19457 if ( y >= 128 && x == 120 )
19458 //!(y<128 && (x!=120) ) )
19459 {
19460 switch(dir)
19461 {
19462 case down:
19463 case l_down:
19464 case r_down:
19465 {
19466 di = nextscr(down);
19467
19468 if(tmpscr->door[1]==dLOCKED)
19469 {
19470 if(usekey())
19471 {
19472 putdoor(scrollbuf,0,down,dUNLOCKED);
19473 tmpscr->door[1]=dUNLOCKED;
19474 setmapflag(si, mDOOR_DOWN);
19475
19476 if(di != 0xFFFF)
19477 setmapflag(di, mDOOR_UP);
19478 sfx(WAV_DOOR);
19479 markBmap(-1);
19480 }
19481 else return;
19482 }
19483 else if(tmpscr->door[1]==dBOSS)
19484 {
19485 if(game->lvlitems[dlevel]&liBOSSKEY)
19486 {
19487 putdoor(scrollbuf,0,down,dOPENBOSS);
19488 tmpscr->door[1]=dOPENBOSS;
19489 setmapflag(si, mDOOR_DOWN);
19490
19491 if(di != 0xFFFF)
19492 setmapflag(di, mDOOR_UP);
19493 sfx(WAV_DOOR);
19494 markBmap(-1);
19495 // Run Boss Key Script
19496 int32_t key_item = 0; //current_item_id(itype_bosskey); //not possible
19497 for ( int32_t q = 0; q < MAXITEMS; ++q )
19498 {
19499 if ( itemsbuf[q].family == itype_bosskey )
19500 {
19501 key_item = q; break;
19502 }
19503 }
19504 if ( key_item > 0 && itemsbuf[key_item].script && !(item_doscript[key_item] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) )
19505 {
19506 ri = &(itemScriptData[key_item]);
19507 for ( int32_t q = 0; q < 1024; q++ ) item_stack[key_item][q] = 0xFFFF;
19508 ri->Clear();
19509 item_doscript[key_item] = 1;
19510 itemscriptInitialised[key_item] = 0;
19511 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[key_item].script, key_item);
19512 FFCore.deallocateAllArrays(SCRIPT_ITEM,(key_item));
19513 }
19514 }
19515 else return;
19516 }
19517 break;
19518 }
19519 default: break;
19520 }
19521 }
19522 //left
19523 if ( y == 80 && x <= 32 )
19524 //!( (y!=80) && x>32 ) )
19525 {
19526 switch(dir)
19527 {
19528 case left:
19529 case l_up:
19530 case l_down:
19531 {
19532 di = nextscr(left);
19533 if(tmpscr->door[2]==dLOCKED)
19534 {
19535 if(usekey())
19536 {
19537 putdoor(scrollbuf,0,left,dUNLOCKED);
19538 tmpscr->door[2]=dUNLOCKED;
19539 setmapflag(si, mDOOR_LEFT);
19540
19541 if(di != 0xFFFF)
19542 setmapflag(di, mDOOR_RIGHT);
19543 sfx(WAV_DOOR);
19544 markBmap(-1);
19545 }
19546 else return;
19547 }
19548 else if(tmpscr->door[2]==dBOSS)
19549 {
19550 if(game->lvlitems[dlevel]&liBOSSKEY)
19551 {
19552 putdoor(scrollbuf,0,left,dOPENBOSS);
19553 tmpscr->door[2]=dOPENBOSS;
19554 setmapflag(si, mDOOR_LEFT);
19555
19556 if(di != 0xFFFF)
19557 setmapflag(di, mDOOR_RIGHT);
19558 sfx(WAV_DOOR);
19559 markBmap(-1);
19560 // Run Boss Key Script
19561 int32_t key_item = 0; //current_item_id(itype_bosskey); //not possible
19562 for ( int32_t q = 0; q < MAXITEMS; ++q )
19563 {
19564 if ( itemsbuf[q].family == itype_bosskey )
19565 {
19566 key_item = q; break;
19567 }
19568 }
19569 if ( key_item > 0 && itemsbuf[key_item].script && !(item_doscript[key_item] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) )
19570 {
19571 ri = &(itemScriptData[key_item]);
19572 for ( int32_t q = 0; q < 1024; q++ ) item_stack[key_item][q] = 0xFFFF;
19573 ri->Clear();
19574 item_doscript[key_item] = 1;
19575 itemscriptInitialised[key_item] = 0;
19576 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[key_item].script, key_item);
19577 FFCore.deallocateAllArrays(SCRIPT_ITEM,(key_item));
19578 }
19579 }
19580 else return;
19581 }
19582
19583 break;
19584
19585 }
19586 default: break;
19587 }
19588 }
19589 //right
19590 if ( y == 80 && x >= 208 )
19591 //!((y!=80) && x<208 ) )
19592 {
19593 switch(dir)
19594 {
19595 case right:
19596 case r_down:
19597 case r_up:
19598 {
19599 di = nextscr(right);
19600 if(tmpscr->door[3]==dLOCKED)
19601 {
19602 if(usekey())
19603 {
19604 putdoor(scrollbuf,0,right,dUNLOCKED);
19605 tmpscr->door[3]=dUNLOCKED;
19606 setmapflag(si, mDOOR_RIGHT);
19607
19608 if(di != 0xFFFF)
19609 setmapflag(di, mDOOR_LEFT);
19610 sfx(WAV_DOOR);
19611 markBmap(-1);
19612 }
19613 else return;
19614 }
19615 else if(tmpscr->door[3]==dBOSS)
19616 {
19617 if(game->lvlitems[dlevel]&liBOSSKEY)
19618 {
19619 putdoor(scrollbuf,0,right,dOPENBOSS);
19620 tmpscr->door[3]=dOPENBOSS;
19621 setmapflag(si, mDOOR_RIGHT);
19622
19623
19624 if(di != 0xFFFF)
19625 setmapflag(di, mDOOR_LEFT);
19626 sfx(WAV_DOOR);
19627 markBmap(-1);
19628 // Run Boss Key Script
19629 int32_t key_item = 0; //current_item_id(itype_bosskey); //not possible
19630 for ( int32_t q = 0; q < MAXITEMS; ++q )
19631 {
19632 if ( itemsbuf[q].family == itype_bosskey )
19633 {
19634 key_item = q; break;
19635 }
19636 }
19637 if ( key_item > 0 && itemsbuf[key_item].script && !(item_doscript[key_item] && get_bit(quest_rules,qr_ITEMSCRIPTSKEEPRUNNING)) ) //
19638 {
19639 ri = &(itemScriptData[key_item]);
19640 for ( int32_t q = 0; q < 1024; q++ ) item_stack[key_item][q] = 0xFFFF;
19641 ri->Clear();
19642 item_doscript[key_item] = 1;
19643 itemscriptInitialised[key_item] = 0;
19644 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[key_item].script, key_item);
19645 FFCore.deallocateAllArrays(SCRIPT_ITEM,(key_item));
19646 }
19647
19648 }
19649 else return;
19650 }
19651
19652
19653 break;
19654 }
19655 default: break;
19656
19657 }
19658 }
19659 }
19660 1888 }
19661
19662 1888 void HeroClass::checkswordtap()
19663 {
19664
3/6
✓ Branch 0 taken 1085 times.
✓ Branch 1 taken 803 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1085 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1888 if(attack!=wSword || charging<=0 || pushing<8) return;
19665
19666 int32_t bx=x;
19667 int32_t by=y+8;
19668
19669 switch(dir)
19670 {
19671 case up:
19672 if(!Up()) return;
19673
19674 by-=16;
19675 break;
19676
19677 case down:
19678 if(!Down()) return;
19679
19680 by+=16;
19681 bx+=8;
19682 break;
19683
19684 case left:
19685 if(!Left()) return;
19686
19687 bx-=16;
19688 by+=8;
19689 break;
19690
19691 case right:
19692 if(!Right()) return;
19693
19694 bx+=16;
19695 by+=8;
19696 break;
19697 }
19698
19699 if(!_walkflag(bx,by,0,SWITCHBLOCK_STATE)) return;
19700
19701 attackclk=SWORDTAPFRAME;
19702 pushing=-8; //16 frames between taps
19703 tapping=true;
19704
19705 int32_t type = COMBOTYPE(bx,by);
19706
19707 if(!isCuttableType(type))
19708 {
19709 bool hollow = (MAPFLAG(bx,by) == mfBOMB || MAPCOMBOFLAG(bx,by) == mfBOMB ||
19710 MAPFLAG(bx,by) == mfSBOMB || MAPCOMBOFLAG(bx,by) == mfSBOMB);
19711
19712 // Layers
19713 for(int32_t i=0; i < 6; i++)
19714 hollow = (hollow || MAPFLAG2(i,bx,by) == mfBOMB || MAPCOMBOFLAG2(i,bx,by) == mfBOMB ||
19715 MAPFLAG2(i,bx,by) == mfSBOMB || MAPCOMBOFLAG2(i,bx,by) == mfSBOMB);
19716
19717 for(int32_t i=0; i<4; i++)
19718 if(tmpscr->door[i]==dBOMB && i==dir)
19719 switch(i)
19720 {
19721 case up:
19722 case down:
19723 if(bx>=112 && bx<144 && (by>=144 || by<=32)) hollow=true;
19724
19725 break;
19726
19727 case left:
19728 case right:
19729 if(by>=72 && by<104 && (bx>=224 || bx<=32)) hollow=true;
19730
19731 break;
19732 }
19733
19734 sfx(hollow ? WAV_ZN1TAP2 : WAV_ZN1TAP,pan(x.getInt()));
19735 }
19736
19737 1888 }
19738
19739 void HeroClass::fairycircle(int32_t type)
19740 {
19741 if(fairyclk==0)
19742 {
19743 switch(type)
19744 {
19745 case REFILL_LIFE:
19746 if(didstuff&did_fairy) return;
19747
19748 didstuff|=did_fairy;
19749 break;
19750
19751 case REFILL_MAGIC:
19752 if(didstuff&did_magic) return;
19753
19754 didstuff|=did_magic;
19755 break;
19756
19757 case REFILL_ALL:
19758 if(didstuff&did_all) return;
19759
19760 didstuff|=did_all;
19761 }
19762
19763 refill_what=type;
19764 refill_why=REFILL_FAIRY;
19765 StartRefill(type);
19766 if (IsSideSwim()) {action=sideswimfreeze; FFCore.setHeroAction(sideswimfreeze);}
19767 else {action=freeze; FFCore.setHeroAction(freeze);}
19768 holdclk=0;
19769 hopclk=0;
19770 }
19771
19772 ++fairyclk;
19773
19774 if(refilling!=REFILL_FAIRYDONE)
19775 {
19776 if(!refill())
19777 refilling=REFILL_FAIRYDONE;
19778 }
19779
19780 else if(++holdclk>80)
19781 {
19782 reset_swordcharge();
19783 attackclk=0;
19784 action=none; FFCore.setHeroAction(none);
19785 fairyclk=0;
19786 holdclk=0;
19787 refill_why = 0;
19788 refilling=REFILL_NONE;
19789 map_bkgsfx(true);
19790 }
19791 }
19792
19793 81 int32_t touchcombo(int32_t x,int32_t y)
19794 {
19795
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 81 times.
243 for (int32_t i = 0; i <= 1; ++i)
19796 {
19797
1/2
✓ Branch 0 taken 162 times.
✗ Branch 1 not taken.
162 if(tmpscr2[i].valid!=0)
19798 {
19799 if (get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
19800 {
19801 if (combobuf[MAPCOMBO2(i,x,y)].type == cBRIDGE && !_walkflag_layer(x,y,1, &(tmpscr2[i]))) return 0;
19802 }
19803 else
19804 {
19805 if (combobuf[MAPCOMBO2(i,x,y)].type == cBRIDGE && _effectflag_layer(x,y,1, &(tmpscr2[i]))) return 0;
19806 }
19807 }
19808 162 }
19809
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 if (!_effectflag(x,y,1, -1)) return 0;
19810 81 newcombo const& cmb = combobuf[MAPCOMBO(x,y)];
19811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if(cmb.triggerflags[0] & combotriggerONLYGENTRIG)
19812 return 0;
19813
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
✗ Branch 2 not taken.
81 switch(cmb.type)
19814 {
19815 case cBSGRAVE:
19816 case cGRAVE:
19817 if(MAPFLAG(x,y)||MAPCOMBOFLAG(x,y)) //!DIMITODO: all flags break graves, not just push flags
19818 {
19819 break;
19820 }
19821
19822 [[fallthrough]];
19823 case cARMOS:
19824 {
19825 return cmb.type;
19826 }
19827 }
19828
19829 81 return 0;
19830 81 }
19831
19832 //static int32_t COMBOX(int32_t pos) { return ((pos)%16*16); }
19833 //static int32_t COMBOY(int32_t pos) { return ((pos)&0xF0); }
19834
19835 static int32_t GridX(int32_t x)
19836 {
19837 return (x >> 4) << 4;
19838 }
19839
19840 //Snaps 'y' to the combo grid
19841 //Equivalent to calling ComboY(ComboAt(foo,y));
19842 static int32_t GridY(int32_t y)
19843 {
19844 return (y >> 4) << 4;
19845 }
19846
19847 int32_t grabComboFromPos(int32_t pos, int32_t type)
19848 {
19849 for(int32_t lyr = 6; lyr > -1; --lyr)
19850 {
19851 int32_t id = FFCore.tempScreens[lyr]->data[pos];
19852 if(combobuf[id].type == type)
19853 return id;
19854 }
19855 return -1;
19856 }
19857
19858 static int32_t typeMap[176];
19859 static int32_t istrig[176];
19860 static const int32_t SPTYPE_SOLID = -1;
19861 #define SP_VISITED 0x1
19862 #define SPFLAG(dir) (0x2<<dir)
19863 #define BEAM_AGE_LIMIT 32
19864 void HeroClass::handleBeam(byte* grid, size_t age, byte spotdir, int32_t curpos, byte set, bool block, bool refl)
19865 {
19866 int32_t trigflag = set ? (1 << (set-1)) : ~0;
19867 if(spotdir > 3) return; //invalid dir
19868 bool doAge = true;
19869 byte f = 0;
19870 while(unsigned(curpos) < 176)
19871 {
19872 bool block_light = false;
19873 f = SPFLAG(spotdir);
19874 if((grid[curpos] & f) != f)
19875 {
19876 grid[curpos] |= f;
19877 istrig[curpos] |= trigflag;
19878 doAge = false;
19879 age = 0;
19880 }
19881 switch(spotdir)
19882 {
19883 case up:
19884 curpos -= 0x10;
19885 break;
19886 case down:
19887 curpos += 0x10;
19888 break;
19889 case left:
19890 if(!(curpos%0x10))
19891 curpos = -1;
19892 else --curpos;
19893 break;
19894 case right:
19895 ++curpos;
19896 if(!(curpos%0x10))
19897 curpos = -1;
19898 break;
19899 }
19900 if(unsigned(curpos) >= 176) break;
19901 switch(typeMap[curpos])
19902 {
19903 case SPTYPE_SOLID: case cBLOCKALL:
19904 curpos = -1;
19905 break;
19906 }
19907 if((curpos==COMBOPOS(x.getInt()+8,y.getInt()+8)) && block && (spotdir == oppositeDir[dir]))
19908 curpos = -1;
19909 if(unsigned(curpos) >= 176) break;
19910
19911 f = SPFLAG(oppositeDir[spotdir]);
19912 if((grid[curpos] & f) != f)
19913 {
19914 grid[curpos] |= f;
19915 istrig[curpos] |= trigflag;
19916 doAge = false;
19917 age = 0;
19918 }
19919 if(doAge)
19920 {
19921 if(++age > BEAM_AGE_LIMIT)
19922 break;
19923 }
19924 else doAge = true;
19925
19926 if(curpos==COMBOPOS(x.getInt()+8,y.getInt() +8) && refl)
19927 spotdir = dir;
19928 else switch(typeMap[curpos])
19929 {
19930 case cLIGHTTARGET:
19931 if(combobuf[grabComboFromPos(curpos, cLIGHTTARGET)].usrflags&cflag3) //Blocks light
19932 return;
19933 case cMIRROR:
19934 spotdir = oppositeDir[spotdir];
19935 break;
19936 case cMIRRORSLASH:
19937 switch(spotdir)
19938 {
19939 case up:
19940 spotdir = right; break;
19941 case right:
19942 spotdir = up; break;
19943 case down:
19944 spotdir = left; break;
19945 case left:
19946 spotdir = down; break;
19947 }
19948 break;
19949 case cMIRRORBACKSLASH:
19950 switch(spotdir)
19951 {
19952 case up:
19953 spotdir = left; break;
19954 case left:
19955 spotdir = up; break;
19956 case down:
19957 spotdir = right; break;
19958 case right:
19959 spotdir = down; break;
19960 }
19961 break;
19962 case cMAGICPRISM:
19963 for(byte d = 0; d < 4; ++d)
19964 {
19965 if(d == oppositeDir[spotdir]) continue;
19966 handleBeam(grid, age, d, curpos, set, block, refl);
19967 }
19968 return;
19969 case cMAGICPRISM4:
19970 for(byte d = 0; d < 4; ++d)
19971 {
19972 handleBeam(grid, age, d, curpos, set, block, refl);
19973 }
19974 return;
19975 }
19976 }
19977 }
19978
19979 1888 void HeroClass::handleSpotlights()
19980 {
19981 typedef byte spot_t;
19982 //Store each different tile/color as grids
19983 1888 std::map<int32_t, spot_t*> maps;
19984
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 int32_t shieldid = getCurrentShield(false);
19985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 bool refl = shieldid > -1 && (itemsbuf[shieldid].misc2 & shLIGHTBEAM);
19986
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
1888 bool block = !refl && shieldid > -1 && (itemsbuf[shieldid].misc1 & shLIGHTBEAM);
19987
3/6
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1888 times.
✗ Branch 5 not taken.
1888 int32_t heropos = COMBOPOS(x.getInt()+8,y.getInt()+8);
19988 1888 memset(istrig, 0, sizeof(istrig));
19989
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 clear_bitmap(lightbeam_bmp);
19990
19991
2/2
✓ Branch 0 taken 332288 times.
✓ Branch 1 taken 1888 times.
334176 for(size_t pos = 0; pos < 176; ++pos)
19992 {
19993 332288 typeMap[pos] = 0;
19994
2/2
✓ Branch 0 taken 332288 times.
✓ Branch 1 taken 2326016 times.
2658304 for(int32_t lyr = 6; lyr > -1; --lyr)
19995 {
19996 2326016 newcombo const* cmb = &combobuf[FFCore.tempScreens[lyr]->data[pos]];
19997
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 2326016 times.
✗ Branch 2 not taken.
2326016 switch(cmb->type)
19998 {
19999 case cMIRROR: case cMIRRORSLASH: case cMIRRORBACKSLASH:
20000 case cMAGICPRISM: case cMAGICPRISM4:
20001 case cBLOCKALL: case cLIGHTTARGET:
20002 typeMap[pos] = cmb->type;
20003 break;
20004 case cGLASS:
20005 typeMap[pos] = 0;
20006 break;
20007 default:
20008 {
20009
4/4
✓ Branch 0 taken 996864 times.
✓ Branch 1 taken 1329152 times.
✓ Branch 2 taken 826042 times.
✓ Branch 3 taken 170822 times.
2326016 if(lyr < 3 && (cmb->walk & 0xF))
20010 {
20011 170822 typeMap[pos] = SPTYPE_SOLID;
20012 170822 }
20013 2326016 continue; //next layer
20014 }
20015 }
20016 break; //hit a combo type
20017 }
20018 332288 }
20019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(unsigned(heropos) < 176)
20020 {
20021
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1877 times.
1888 switch(typeMap[heropos])
20022 {
20023 case SPTYPE_SOLID: case cBLOCKALL:
20024 11 heropos = -1; //Blocked from hitting player
20025 11 }
20026 1888 }
20027
20028
2/2
✓ Branch 0 taken 13216 times.
✓ Branch 1 taken 1888 times.
15104 for(size_t layer = 0; layer < 7; ++layer)
20029 {
20030 13216 mapscr* curlayer = FFCore.tempScreens[layer];
20031
2/2
✓ Branch 0 taken 2326016 times.
✓ Branch 1 taken 13216 times.
2339232 for(size_t pos = 0; pos < 176; ++pos)
20032 {
20033 //For each spotlight combo on each layer...
20034 2326016 newcombo const& cmb = combobuf[curlayer->data[pos]];
20035
1/2
✓ Branch 0 taken 2326016 times.
✗ Branch 1 not taken.
2326016 if(cmb.type == cSPOTLIGHT)
20036 {
20037 //Positive ID is a tile, negative is a color trio. 0 is nil in either case.
20038 int32_t id = (cmb.usrflags&cflag1)
20039 ? std::max(0,cmb.attributes[0]/10000)|(cmb.attribytes[1]%12)<<24
20040 : -((cmb.attribytes[3]<<16)|(cmb.attribytes[2]<<8)|(cmb.attribytes[1]));
20041 if(!id) continue;
20042 // zprint2("ID = %ld\n", id);
20043 //Get the grid array for this tile/color
20044 spot_t* grid;
20045 if(maps[id])
20046 grid = maps[id];
20047 else
20048 {
20049 grid = new spot_t[176];
20050 memset(grid, 0, sizeof(spot_t)*176);
20051 maps[id] = grid;
20052 }
20053 byte spotdir = cmb.attribytes[0];
20054 int32_t curpos = pos;
20055 if(spotdir > 3)
20056 {
20057 grid[curpos] |= SP_VISITED;
20058 istrig[curpos] |= cmb.attribytes[4] ? (1 << (cmb.attribytes[4]-1)) : ~0;
20059 }
20060 if(refl && curpos == heropos)
20061 {
20062 spotdir = dir;
20063 }
20064 handleBeam(grid, 0, spotdir, curpos, cmb.attribytes[4], block, refl);
20065 }
20066 2326016 }
20067 13216 }
20068
20069 //Draw visuals
20070
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1888 times.
1888 for(auto it = maps.begin(); it != maps.end();)
20071 {
20072 int32_t id = it->first;
20073 spot_t* grid = it->second;
20074 //
20075 enum {t_gr, t_up, t_down, t_left, t_right, t_uleft, t_uright, t_dleft, t_dright, t_vert, t_horz, t_notup, t_notdown, t_notleft, t_notright, t_all, t_max };
20076 int32_t tile = (id&0xFFFFFF);
20077 int32_t cs = (id>>24);
20078 byte c_inner = ((-id)&0x0000FF);
20079 byte c_middle = ((-id)&0x00FF00)>>8;
20080 byte c_outter = ((-id)&0xFF0000)>>16;
20081 //{ Setup color bitmap
20082 BITMAP* cbmp = NULL;
20083 if(id < 0)
20084 {
20085 //zprint2("Creating with colors: %02X,%02X,%02X\n", c_inner, c_middle, c_outter);
20086 cbmp = create_bitmap_ex(8, 16*t_max, 16);
20087 clear_bitmap(cbmp);
20088 for(size_t q = 1; q < t_max; ++q)
20089 {
20090 circlefill(cbmp, 16*q+8, 8, 3, c_outter);
20091 circlefill(cbmp, 16*q+7, 8, 3, c_outter);
20092 circlefill(cbmp, 16*q+8, 7, 3, c_outter);
20093 circlefill(cbmp, 16*q+7, 7, 3, c_outter);
20094 circlefill(cbmp, 16*q+8, 8, 1, c_middle);
20095 circlefill(cbmp, 16*q+7, 8, 1, c_middle);
20096 circlefill(cbmp, 16*q+8, 7, 1, c_middle);
20097 circlefill(cbmp, 16*q+7, 7, 1, c_middle);
20098 circlefill(cbmp, 16*q+8, 8, 0, c_inner);
20099 circlefill(cbmp, 16*q+7, 8, 0, c_inner);
20100 circlefill(cbmp, 16*q+8, 7, 0, c_inner);
20101 circlefill(cbmp, 16*q+7, 7, 0, c_inner);
20102 }
20103 //t_gr
20104 circlefill(cbmp, 16*t_gr+8, 8, 7, c_outter);
20105 circlefill(cbmp, 16*t_gr+7, 8, 7, c_outter);
20106 circlefill(cbmp, 16*t_gr+8, 7, 7, c_outter);
20107 circlefill(cbmp, 16*t_gr+7, 7, 7, c_outter);
20108 circlefill(cbmp, 16*t_gr+8, 8, 5, c_middle);
20109 circlefill(cbmp, 16*t_gr+7, 8, 5, c_middle);
20110 circlefill(cbmp, 16*t_gr+8, 7, 5, c_middle);
20111 circlefill(cbmp, 16*t_gr+7, 7, 5, c_middle);
20112 circlefill(cbmp, 16*t_gr+8, 8, 3, c_inner);
20113 circlefill(cbmp, 16*t_gr+7, 8, 3, c_inner);
20114 circlefill(cbmp, 16*t_gr+8, 7, 3, c_inner);
20115 circlefill(cbmp, 16*t_gr+7, 7, 3, c_inner);
20116 //t_up
20117 rectfill(cbmp, 16*t_up+4, 0, 16*t_up+11, 7, c_outter);
20118 rectfill(cbmp, 16*t_up+6, 0, 16*t_up+9, 7, c_middle);
20119 rectfill(cbmp, 16*t_up+7, 0, 16*t_up+8, 7, c_inner);
20120 //t_down
20121 rectfill(cbmp, 16*t_down+4, 8, 16*t_down+11, 15, c_outter);
20122 rectfill(cbmp, 16*t_down+6, 8, 16*t_down+9, 15, c_middle);
20123 rectfill(cbmp, 16*t_down+7, 8, 16*t_down+8, 15, c_inner);
20124 //t_left
20125 rectfill(cbmp, 16*t_left, 4, 16*t_left+7, 11, c_outter);
20126 rectfill(cbmp, 16*t_left, 6, 16*t_left+7, 9, c_middle);
20127 rectfill(cbmp, 16*t_left, 7, 16*t_left+7, 8, c_inner);
20128 //t_right
20129 rectfill(cbmp, 16*t_right+8, 4, 16*t_right+15, 11, c_outter);
20130 rectfill(cbmp, 16*t_right+8, 6, 16*t_right+15, 9, c_middle);
20131 rectfill(cbmp, 16*t_right+8, 7, 16*t_right+15, 8, c_inner);
20132 //t_uleft
20133 rectfill(cbmp, 16*t_uleft+4, 0, 16*t_uleft+11, 7, c_outter);
20134 rectfill(cbmp, 16*t_uleft, 4, 16*t_uleft+7, 11, c_outter);
20135 rectfill(cbmp, 16*t_uleft, 6, 16*t_uleft+7, 9, c_middle);
20136 rectfill(cbmp, 16*t_uleft+6, 0, 16*t_uleft+9, 7, c_middle);
20137 rectfill(cbmp, 16*t_uleft+7, 0, 16*t_uleft+8, 7, c_inner);
20138 rectfill(cbmp, 16*t_uleft, 7, 16*t_uleft+7, 8, c_inner);
20139 //t_uright
20140 rectfill(cbmp, 16*t_uright+4, 0, 16*t_uright+11, 7, c_outter);
20141 rectfill(cbmp, 16*t_uright+8, 4, 16*t_uright+15, 11, c_outter);
20142 rectfill(cbmp, 16*t_uright+8, 6, 16*t_uright+15, 9, c_middle);
20143 rectfill(cbmp, 16*t_uright+6, 0, 16*t_uright+9, 7, c_middle);
20144 rectfill(cbmp, 16*t_uright+7, 0, 16*t_uright+8, 7, c_inner);
20145 rectfill(cbmp, 16*t_uright+8, 7, 16*t_uright+15, 8, c_inner);
20146 //t_dleft
20147 rectfill(cbmp, 16*t_dleft+4, 8, 16*t_dleft+11, 15, c_outter);
20148 rectfill(cbmp, 16*t_dleft, 4, 16*t_dleft+7, 11, c_outter);
20149 rectfill(cbmp, 16*t_dleft, 6, 16*t_dleft+7, 9, c_middle);
20150 rectfill(cbmp, 16*t_dleft+6, 8, 16*t_dleft+9, 15, c_middle);
20151 rectfill(cbmp, 16*t_dleft+7, 8, 16*t_dleft+8, 15, c_inner);
20152 rectfill(cbmp, 16*t_dleft, 7, 16*t_dleft+7, 8, c_inner);
20153 //t_dright
20154 rectfill(cbmp, 16*t_dright+4, 8, 16*t_dright+11, 15, c_outter);
20155 rectfill(cbmp, 16*t_dright+8, 4, 16*t_dright+15, 11, c_outter);
20156 rectfill(cbmp, 16*t_dright+8, 6, 16*t_dright+15, 9, c_middle);
20157 rectfill(cbmp, 16*t_dright+6, 8, 16*t_dright+9, 15, c_middle);
20158 rectfill(cbmp, 16*t_dright+7, 8, 16*t_dright+8, 15, c_inner);
20159 rectfill(cbmp, 16*t_dright+8, 7, 16*t_dright+15, 8, c_inner);
20160 //t_vert
20161 rectfill(cbmp, 16*t_vert+4, 0, 16*t_vert+11, 15, c_outter);
20162 rectfill(cbmp, 16*t_vert+6, 0, 16*t_vert+9, 15, c_middle);
20163 rectfill(cbmp, 16*t_vert+7, 0, 16*t_vert+8, 15, c_inner);
20164 //t_horz
20165 rectfill(cbmp, 16*t_horz, 4, 16*t_horz+15, 11, c_outter);
20166 rectfill(cbmp, 16*t_horz, 6, 16*t_horz+15, 9, c_middle);
20167 rectfill(cbmp, 16*t_horz, 7, 16*t_horz+15, 8, c_inner);
20168 //t_notup
20169 rectfill(cbmp, 16*t_notup, 4, 16*t_notup+15, 11, c_outter);
20170 rectfill(cbmp, 16*t_notup+4, 8, 16*t_notup+11, 15, c_outter);
20171 rectfill(cbmp, 16*t_notup+6, 8, 16*t_notup+9, 15, c_middle);
20172 rectfill(cbmp, 16*t_notup, 6, 16*t_notup+15, 9, c_middle);
20173 rectfill(cbmp, 16*t_notup, 7, 16*t_notup+15, 8, c_inner);
20174 rectfill(cbmp, 16*t_notup+7, 8, 16*t_notup+8, 15, c_inner);
20175 //t_notdown
20176 rectfill(cbmp, 16*t_notdown, 4, 16*t_notdown+15, 11, c_outter);
20177 rectfill(cbmp, 16*t_notdown+4, 0, 16*t_notdown+11, 7, c_outter);
20178 rectfill(cbmp, 16*t_notdown+6, 0, 16*t_notdown+9, 7, c_middle);
20179 rectfill(cbmp, 16*t_notdown, 6, 16*t_notdown+15, 9, c_middle);
20180 rectfill(cbmp, 16*t_notdown, 7, 16*t_notdown+15, 8, c_inner);
20181 rectfill(cbmp, 16*t_notdown+7, 0, 16*t_notdown+8, 7, c_inner);
20182 //t_notleft
20183 rectfill(cbmp, 16*t_notleft+4, 0, 16*t_notleft+11, 15, c_outter);
20184 rectfill(cbmp, 16*t_notleft+8, 4, 16*t_notleft+15, 11, c_outter);
20185 rectfill(cbmp, 16*t_notleft+8, 6, 16*t_notleft+15, 9, c_middle);
20186 rectfill(cbmp, 16*t_notleft+6, 0, 16*t_notleft+9, 15, c_middle);
20187 rectfill(cbmp, 16*t_notleft+7, 0, 16*t_notleft+8, 15, c_inner);
20188 rectfill(cbmp, 16*t_notleft+8, 7, 16*t_notleft+15, 8, c_inner);
20189 //t_notright
20190 rectfill(cbmp, 16*t_notright+4, 0, 16*t_notright+11, 15, c_outter);
20191 rectfill(cbmp, 16*t_notright, 4, 16*t_notright+7, 11, c_outter);
20192 rectfill(cbmp, 16*t_notright, 6, 16*t_notright+7, 9, c_middle);
20193 rectfill(cbmp, 16*t_notright+6, 0, 16*t_notright+9, 15, c_middle);
20194 rectfill(cbmp, 16*t_notright+7, 0, 16*t_notright+8, 15, c_inner);
20195 rectfill(cbmp, 16*t_notright, 7, 16*t_notright+7, 8, c_inner);
20196 //t_all
20197 rectfill(cbmp, 16*t_all+4, 0, 16*t_all+11, 15, c_outter);
20198 rectfill(cbmp, 16*t_all, 4, 16*t_all+15, 11, c_outter);
20199 rectfill(cbmp, 16*t_all, 6, 16*t_all+15, 9, c_middle);
20200 rectfill(cbmp, 16*t_all+6, 0, 16*t_all+9, 15, c_middle);
20201 rectfill(cbmp, 16*t_all+7, 0, 16*t_all+8, 15, c_inner);
20202 rectfill(cbmp, 16*t_all, 7, 16*t_all+15, 8, c_inner);
20203 }
20204 //}
20205 //
20206 for(size_t pos = 0; pos < 176; ++pos)
20207 {
20208 int32_t offs = -1;
20209 switch(grid[pos]>>1)
20210 {
20211 case 0: default:
20212 if(grid[pos])
20213 {
20214 offs = t_gr;
20215 break;
20216 }
20217 continue; //no draw this pos
20218 case 0b0001:
20219 offs = t_up;
20220 break;
20221 case 0b0010:
20222 offs = t_down;
20223 break;
20224 case 0b0100:
20225 offs = t_left;
20226 break;
20227 case 0b1000:
20228 offs = t_right;
20229 break;
20230 case 0b0011:
20231 offs = t_vert;
20232 break;
20233 case 0b1100:
20234 offs = t_horz;
20235 break;
20236 case 0b0101:
20237 offs = t_uleft;
20238 break;
20239 case 0b1001:
20240 offs = t_uright;
20241 break;
20242 case 0b0110:
20243 offs = t_dleft;
20244 break;
20245 case 0b1010:
20246 offs = t_dright;
20247 break;
20248 case 0b1110:
20249 offs = t_notup;
20250 break;
20251 case 0b1101:
20252 offs = t_notdown;
20253 break;
20254 case 0b1011:
20255 offs = t_notleft;
20256 break;
20257 case 0b0111:
20258 offs = t_notright;
20259 break;
20260 case 0b1111:
20261 offs = t_all;
20262 break;
20263 }
20264 if(id > 0) //tile
20265 {
20266 //Draw 'tile' at 'pos'
20267 overtile16(lightbeam_bmp, tile+offs, COMBOX(pos), COMBOY(pos), cs, 0);
20268 }
20269 else //colors
20270 {
20271 masked_blit(cbmp, lightbeam_bmp, offs*16, 0, COMBOX(pos), COMBOY(pos), 16, 16);
20272 }
20273 }
20274 //
20275 if(cbmp) destroy_bitmap(cbmp);
20276 delete[] it->second;
20277 it = maps.erase(it);
20278 }
20279 //Check triggers
20280 1888 bool hastrigs = false, istrigged = true;
20281
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 bool alltrig = getmapflag(mLIGHTBEAM);
20282
2/2
✓ Branch 0 taken 13216 times.
✓ Branch 1 taken 1888 times.
15104 for(size_t layer = 0; layer < 7; ++layer)
20283 {
20284 13216 mapscr* curlayer = FFCore.tempScreens[layer];
20285
2/2
✓ Branch 0 taken 2326016 times.
✓ Branch 1 taken 13216 times.
2339232 for(size_t pos = 0; pos < 176; ++pos)
20286 {
20287 2326016 newcombo const* cmb = &combobuf[curlayer->data[pos]];
20288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2326016 times.
2326016 if(cmb->type == cLIGHTTARGET)
20289 {
20290 int32_t trigflag = cmb->attribytes[4] ? (1 << (cmb->attribytes[4]-1)) : ~0;
20291 hastrigs = true;
20292 bool trigged = (istrig[pos]&trigflag);
20293 if(cmb->usrflags&cflag2) //Invert
20294 trigged = !trigged;
20295 if(cmb->usrflags&cflag1) //Solved Version
20296 {
20297 if(!(alltrig || trigged)) //Revert
20298 {
20299 curlayer->data[pos] -= 1;
20300 istrigged = false;
20301 }
20302 }
20303 else //Unsolved version
20304 {
20305 if(alltrig || trigged) //Light
20306 curlayer->data[pos] += 1;
20307 else istrigged = false;
20308 }
20309 }
20310
1/2
✓ Branch 0 taken 2326016 times.
✗ Branch 1 not taken.
2326016 else if(cmb->triggerflags[1] & (combotriggerLIGHTON|combotriggerLIGHTOFF))
20311 {
20312 int32_t trigflag = cmb->triglbeam ? (1 << (cmb->triglbeam-1)) : ~0;
20313 bool trigged = (istrig[pos]&trigflag);
20314 if(trigged ? (cmb->triggerflags[1] & combotriggerLIGHTON)
20315 : (cmb->triggerflags[1] & combotriggerLIGHTOFF))
20316 {
20317 do_trigger_combo(layer, pos);
20318 }
20319 }
20320 2326016 }
20321 13216 }
20322
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1888 if(hastrigs && istrigged && !alltrig)
20323 {
20324 hidden_entrance(0,true,false,-7);
20325 sfx(tmpscr->secretsfx);
20326 if(!(tmpscr->flags5&fTEMPSECRETS))
20327 {
20328 setmapflag(mSECRET);
20329 setmapflag(mLIGHTBEAM);
20330 }
20331 }
20332 1888 }
20333
20334 1888 void HeroClass::checktouchblk()
20335 {
20336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(toogam) return;
20337
20338
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 1838 times.
1888 if(!pushing)
20339 1838 return;
20340
20341 50 int32_t tdir = dir; //Bad hack #2. _L_, your welcome to fix this properly. ;)
20342
20343
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
50 if(charging > 0 || spins > 0) //if not I probably will at some point...
20344 {
20345 if(Up()&&Left())tdir = (charging%2)*2;
20346 else if(Up()&&Right())tdir = (charging%2)*3;
20347 else if(Down()&&Left())tdir = 1+(charging%2)*1;
20348 else if(Down()&&Right())tdir = 1+(charging%2)*2;
20349 else
20350 {
20351 if(Up())tdir=0;
20352 else if(Down())tdir=1;
20353 else if(Left())tdir=2;
20354 else if(Right())tdir=3;
20355 }
20356 }
20357
20358 50 int32_t tx=0,ty=-1;
20359
20360
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 4 times.
50 switch(tdir)
20361 {
20362 case up:
20363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if(touchcombo(x,y+(bigHitbox?0:7)))
20364 {
20365 tx=x;
20366 ty=y+(bigHitbox?0:7);
20367 }
20368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 else if(touchcombo(x+8,y+(bigHitbox?0:7)))
20369 {
20370 tx=x+8;
20371 ty=y+(bigHitbox?0:7);
20372 }
20373
20374 26 break;
20375
20376 case down:
20377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(touchcombo(x,y+16))
20378 {
20379 tx=x;
20380 ty=y+16;
20381 }
20382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 else if(touchcombo(x+8,y+16))
20383 {
20384 tx=x+8;
20385 ty=y+16;
20386 }
20387
20388 5 break;
20389
20390 case left:
20391
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if(touchcombo(x-1,y+15))
20392 {
20393 tx=x-1;
20394 ty=y+15;
20395 }
20396
20397 15 break;
20398
20399 case right:
20400
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if(touchcombo(x+16,y+15))
20401 {
20402 tx=x+16;
20403 ty=y+15;
20404 }
20405
20406 4 break;
20407 }
20408
20409
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 if(ty>=0)
20410 {
20411 ty&=0xF0;
20412 tx&=0xF0;
20413 int32_t di = ty+(tx>>4);
20414 if((getAction() != hopping || isSideViewHero()))
20415 {
20416 trigger_armos_grave(0, di, dir);
20417 }
20418 }
20419 1888 }
20420
20421 int32_t HeroClass::nextcombo(int32_t cx, int32_t cy, int32_t cdir)
20422 {
20423 switch(cdir)
20424 {
20425 case up:
20426 cy-=16;
20427 break;
20428
20429 case down:
20430 cy+=16;
20431 break;
20432
20433 case left:
20434 cx-=16;
20435 break;
20436
20437 case right:
20438 cx+=16;
20439 break;
20440 }
20441
20442 // off the screen
20443 if(cx<0 || cy<0 || cx>255 || cy>175)
20444 {
20445 int32_t ns = nextscr(cdir);
20446
20447 if(ns==0xFFFF) return 0;
20448
20449 // want actual screen index, not game->maps[] index
20450 ns = (ns&127) + (ns>>7)*MAPSCRS;
20451
20452 switch(cdir)
20453 {
20454 case up:
20455 cy=160;
20456 break;
20457
20458 case down:
20459 cy=0;
20460 break;
20461
20462 case left:
20463 cx=240;
20464 break;
20465
20466 case right:
20467 cx=0;
20468 break;
20469 }
20470
20471 // from MAPCOMBO()
20472 int32_t cmb = (cy&0xF0)+(cx>>4);
20473
20474 if(cmb>175)
20475 return 0;
20476
20477 return TheMaps[ns].data[cmb]; // entire combo code
20478 }
20479
20480 return MAPCOMBO(cx,cy);
20481 }
20482
20483 int32_t HeroClass::nextflag(int32_t cx, int32_t cy, int32_t cdir, bool comboflag)
20484 {
20485 switch(cdir)
20486 {
20487 case up:
20488 cy-=16;
20489 break;
20490
20491 case down:
20492 cy+=16;
20493 break;
20494
20495 case left:
20496 cx-=16;
20497 break;
20498
20499 case right:
20500 cx+=16;
20501 break;
20502 }
20503
20504 // off the screen
20505 if(cx<0 || cy<0 || cx>255 || cy>175)
20506 {
20507 int32_t ns = nextscr(cdir);
20508
20509 if(ns==0xFFFF) return 0;
20510
20511 // want actual screen index, not game->maps[] index
20512 ns = (ns&127) + (ns>>7)*MAPSCRS;
20513
20514 switch(cdir)
20515 {
20516 case up:
20517 cy=160;
20518 break;
20519
20520 case down:
20521 cy=0;
20522 break;
20523
20524 case left:
20525 cx=240;
20526 break;
20527
20528 case right:
20529 cx=0;
20530 break;
20531 }
20532
20533 // from MAPCOMBO()
20534 int32_t cmb = (cy&0xF0)+(cx>>4);
20535
20536 if(cmb>175)
20537 return 0;
20538
20539 if(!comboflag)
20540 {
20541 return TheMaps[ns].sflag[cmb]; // flag
20542 }
20543 else
20544 {
20545 return combobuf[TheMaps[ns].data[cmb]].flag; // flag
20546 }
20547 }
20548
20549 if(comboflag)
20550 {
20551 return MAPCOMBOFLAG(cx,cy);
20552 }
20553
20554 return MAPFLAG(cx,cy);
20555 }
20556
20557 bool did_secret;
20558
20559 1888 void HeroClass::checkspecial()
20560 {
20561 1888 checktouchblk();
20562
20563 1888 bool hasmainguy = hasMainGuy(); // calculate it once
20564
20565
4/4
✓ Branch 0 taken 1760 times.
✓ Branch 1 taken 128 times.
✓ Branch 2 taken 1136 times.
✓ Branch 3 taken 624 times.
1888 if(!(loaded_enemies && !hasmainguy))
20566 1264 did_secret=false;
20567 else
20568 {
20569 // after beating enemies
20570
20571 // item
20572
1/2
✓ Branch 0 taken 624 times.
✗ Branch 1 not taken.
624 if(hasitem&(4|2|1))
20573 {
20574 int32_t Item=tmpscr->item;
20575
20576 //if(getmapflag())
20577 // Item=0;
20578 if((!getmapflag(mITEM) || (tmpscr->flags9&fITEMRETURN)) && (tmpscr->hasitem != 0))
20579 {
20580 if(hasitem==1)
20581 sfx(WAV_CLEARED);
20582
20583 items.add(new item((zfix)tmpscr->itemx,
20584 (tmpscr->flags7&fITEMFALLS && isSideViewHero()) ? (zfix)-170 : (zfix)tmpscr->itemy+1,
20585 (tmpscr->flags7&fITEMFALLS && !isSideViewHero()) ? (zfix)170 : (zfix)0,
20586 Item,ipONETIME|ipBIGRANGE|((itemsbuf[Item].family==itype_triforcepiece ||
20587 (tmpscr->flags3&fHOLDITEM)) ? ipHOLDUP : 0) | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0),0));
20588 }
20589
20590 hasitem &= ~ (4|2|1);
20591 }
20592
20593 // generic 'Enemies->' trigger
20594
2/2
✓ Branch 0 taken 4368 times.
✓ Branch 1 taken 624 times.
4992 for(auto lyr = 0; lyr < 7; ++lyr)
20595 {
20596
2/2
✓ Branch 0 taken 768768 times.
✓ Branch 1 taken 4368 times.
773136 for(auto pos = 0; pos < 176; ++pos)
20597 {
20598 768768 newcombo const& cmb = combobuf[FFCore.tempScreens[lyr]->data[pos]];
20599
1/2
✓ Branch 0 taken 768768 times.
✗ Branch 1 not taken.
768768 if(cmb.triggerflags[2] & combotriggerKILLENEMIES)
20600 {
20601 do_trigger_combo(lyr,pos);
20602 }
20603 768768 }
20604 4368 }
20605
1/2
✓ Branch 0 taken 624 times.
✗ Branch 1 not taken.
624 if(tmpscr->flags9 & fENEMY_WAVES)
20606 {
20607 hasmainguy = hasMainGuy(); //possibly un-beat the enemies (another 'wave'?)
20608 }
20609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 624 times.
624 if(!hasmainguy)
20610 {
20611 // if room has traps, guys don't come back
20612
2/2
✓ Branch 0 taken 319488 times.
✓ Branch 1 taken 624 times.
320112 for(int32_t i=0; i<eMAXGUYS; i++)
20613 {
20614
4/4
✓ Branch 0 taken 9360 times.
✓ Branch 1 taken 310128 times.
✓ Branch 2 taken 1248 times.
✓ Branch 3 taken 8112 times.
319488 if(guysbuf[i].family==eeTRAP&&guysbuf[i].misc2)
20615
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1248 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1248 if(guys.idCount(i) && !getmapflag(mTMPNORET))
20616 setmapflag(mTMPNORET);
20617 319488 }
20618 // clear enemies and open secret
20619
2/4
✓ Branch 0 taken 624 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 624 times.
✗ Branch 3 not taken.
624 if(!did_secret && (tmpscr->flags2&fCLEARSECRET))
20620 {
20621 bool only16_31 = get_bit(quest_rules,qr_ENEMIES_SECRET_ONLY_16_31)?true:false;
20622 hidden_entrance(0,true,only16_31,-2);
20623
20624 if(tmpscr->flags4&fENEMYSCRTPERM && canPermSecret())
20625 {
20626 if(!(tmpscr->flags5&fTEMPSECRETS)) setmapflag(mSECRET);
20627 }
20628
20629 sfx(tmpscr->secretsfx);
20630 did_secret=true;
20631 }
20632 624 }
20633 }
20634
20635 // doors
20636
2/2
✓ Branch 0 taken 1888 times.
✓ Branch 1 taken 7552 times.
9440 for(int32_t i=0; i<4; i++)
20637
1/2
✓ Branch 0 taken 7552 times.
✗ Branch 1 not taken.
7552 if(tmpscr->door[i]==dSHUTTER)
20638 {
20639 if(opendoors==0 && loaded_enemies)
20640 {
20641 if(!(tmpscr->flags&fSHUTTERS) && !hasmainguy)
20642 opendoors=12;
20643 }
20644 else if(opendoors<0)
20645 ++opendoors;
20646 else if((--opendoors)==0)
20647 openshutters();
20648
20649 break;
20650 }
20651
20652 // set boss flag when boss is gone
20653
3/6
✓ Branch 0 taken 1760 times.
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1760 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1888 if(loaded_enemies && tmpscr->enemyflags&efBOSS && !hasmainguy)
20654 {
20655 game->lvlitems[dlevel]|=liBOSS;
20656 stop_sfx(tmpscr->bosssfx);
20657 }
20658
20659
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(getmapflag(mCHEST)) // if special stuff done before
20660 {
20661 remove_chests((currscr>=128)?1:0);
20662 }
20663
20664
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(getmapflag(mLOCKEDCHEST)) // if special stuff done before
20665 {
20666 remove_lockedchests((currscr>=128)?1:0);
20667 }
20668
20669
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(getmapflag(mBOSSCHEST)) // if special stuff done before
20670 {
20671 remove_bosschests((currscr>=128)?1:0);
20672 }
20673
20674 1888 clear_xstatecombos((currscr>=128)?1:0);
20675
20676
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if((hasitem&8) && triggered_screen_secrets)
20677 {
20678 int32_t Item=tmpscr->item;
20679
20680 if((!getmapflag(mITEM) || (tmpscr->flags9&fITEMRETURN)) && (tmpscr->hasitem != 0))
20681 {
20682 items.add(new item((zfix)tmpscr->itemx,
20683 (tmpscr->flags7&fITEMFALLS && isSideViewHero()) ? (zfix)-170 : (zfix)tmpscr->itemy+1,
20684 (tmpscr->flags7&fITEMFALLS && !isSideViewHero()) ? (zfix)170 : (zfix)0,
20685 Item,ipONETIME|ipBIGRANGE|((itemsbuf[Item].family==itype_triforcepiece ||
20686 (tmpscr->flags3&fHOLDITEM)) ? ipHOLDUP : 0) | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0),0));
20687 }
20688
20689 hasitem &= ~8;
20690 }
20691 1888 }
20692
20693 //Gets the 4 comboposes indicated by the coordinates, replacing duplicates with '-1'
20694 956 void getPoses(int32_t* poses, int32_t x1, int32_t y1, int32_t x2, int32_t y2)
20695 {
20696 int32_t tmp;
20697 956 poses[0] = COMBOPOS(x1,y1);
20698
20699 956 tmp = COMBOPOS(x1,y2);
20700
2/2
✓ Branch 0 taken 675 times.
✓ Branch 1 taken 281 times.
956 if(tmp == poses[0])
20701 675 poses[1] = -1;
20702 281 else poses[1] = tmp;
20703
20704 956 tmp = COMBOPOS(x2,y1);
20705
3/4
✓ Branch 0 taken 544 times.
✓ Branch 1 taken 412 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 544 times.
956 if(tmp == poses[0] || tmp == poses[1])
20706 412 poses[2] = -1;
20707 544 else poses[2] = tmp;
20708
20709 956 tmp = COMBOPOS(x2,y2);
20710
6/6
✓ Branch 0 taken 643 times.
✓ Branch 1 taken 313 times.
✓ Branch 2 taken 544 times.
✓ Branch 3 taken 99 times.
✓ Branch 4 taken 362 times.
✓ Branch 5 taken 182 times.
956 if(tmp == poses[0] || tmp == poses[1] || tmp == poses[2])
20711 774 poses[3] = -1;
20712 182 else poses[3] = tmp;
20713 956 }
20714
20715 1888 void HeroClass::checkspecial2(int32_t *ls)
20716 {
20717
3/6
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1888 times.
1888 if(get_bit(quest_rules,qr_OLDSTYLEWARP) && !(diagonalMovement||NO_GRIDLOCK))
20718 {
20719
2/2
✓ Branch 0 taken 377 times.
✓ Branch 1 taken 1511 times.
1888 if(y.getInt()&7)
20720 377 return;
20721
20722
2/2
✓ Branch 0 taken 794 times.
✓ Branch 1 taken 717 times.
1511 if(x.getInt()&7)
20723 794 return;
20724 717 }
20725
20726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 717 times.
717 if(toogam) return;
20727
20728 717 bool didstrig = false;
20729
20730
2/2
✓ Branch 0 taken 1434 times.
✓ Branch 1 taken 717 times.
2151 for(int32_t i=bigHitbox?0:8; i<16; i+=bigHitbox?15:7)
20731 {
20732
4/4
✓ Branch 0 taken 2868 times.
✓ Branch 1 taken 1434 times.
✓ Branch 2 taken 5736 times.
✓ Branch 3 taken 2868 times.
10038 for(int32_t j=0; j<16; j+=15) for(int32_t k=0; k<2; k++)
20733 {
20734
2/2
✓ Branch 0 taken 2868 times.
✓ Branch 1 taken 2868 times.
5736 newcombo const& cmb = combobuf[k>0 ? MAPFFCOMBO(x+j,y+i) : MAPCOMBO(x+j,y+i)];
20735 5736 int32_t stype = cmb.type;
20736 5736 int32_t warpsound = cmb.attribytes[0];
20737
1/2
✓ Branch 0 taken 5736 times.
✗ Branch 1 not taken.
5736 if(cmb.triggerflags[0] & combotriggerONLYGENTRIG)
20738 stype = cNONE;
20739
1/2
✓ Branch 0 taken 5736 times.
✗ Branch 1 not taken.
5736 if(stype==cSWARPA)
20740 {
20741 if(tmpscr->flags5&fDIRECTSWARP)
20742 {
20743 didpit=true;
20744 pitx=x;
20745 pity=y;
20746 }
20747
20748 sdir=dir;
20749 dowarp(0,0,warpsound);
20750 return;
20751 }
20752
20753
1/2
✓ Branch 0 taken 5736 times.
✗ Branch 1 not taken.
5736 if(stype==cSWARPB)
20754 {
20755 if(tmpscr->flags5&fDIRECTSWARP)
20756 {
20757 didpit=true;
20758 pitx=x;
20759 pity=y;
20760 }
20761
20762 sdir=dir;
20763 dowarp(0,1,warpsound);
20764 return;
20765 }
20766
20767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5736 times.
5736 if(stype==cSWARPC)
20768 {
20769 if(tmpscr->flags5&fDIRECTSWARP)
20770 {
20771 didpit=true;
20772 pitx=x;
20773 pity=y;
20774 }
20775
20776 sdir=dir;
20777 dowarp(0,2,warpsound);
20778 return;
20779 }
20780
20781
1/2
✓ Branch 0 taken 5736 times.
✗ Branch 1 not taken.
5736 if(stype==cSWARPD)
20782 {
20783 if(tmpscr->flags5&fDIRECTSWARP)
20784 {
20785 didpit=true;
20786 pitx=x;
20787 pity=y;
20788 }
20789
20790 sdir=dir;
20791 dowarp(0,3,warpsound);
20792 return;
20793 }
20794
20795
1/2
✓ Branch 0 taken 5736 times.
✗ Branch 1 not taken.
5736 if(stype==cSWARPR)
20796 {
20797 if(tmpscr->flags5&fDIRECTSWARP)
20798 {
20799 didpit=true;
20800 pitx=x;
20801 pity=y;
20802 }
20803
20804 sdir=dir;
20805 dowarp(0,(zc_oldrand()%4),warpsound);
20806 return;
20807 }
20808
20809
3/6
✓ Branch 0 taken 5736 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5736 times.
✓ Branch 4 taken 5736 times.
✗ Branch 5 not taken.
5736 if((stype==cSTRIGNOFLAG || stype==cSTRIGFLAG) && stepsecret!=MAPCOMBO(x+j,y+i))
20810 {
20811 // zprint("Step Secs\n");
20812 if(stype==cSTRIGFLAG && canPermSecret())
20813 {
20814 if(!didstrig)
20815 {
20816 stepsecret = ((int32_t)(y+i)&0xF0)+((int32_t)(x+j)>>4);
20817
20818 if(!(tmpscr->flags5&fTEMPSECRETS))
20819 {
20820 setmapflag(mSECRET);
20821 }
20822 //int32_t thesfx = combobuf[MAPCOMBO(x+j,y+i)].attribytes[0];
20823 //zprint("Step Secrets SFX: %d\n", thesfx);
20824 sfx(warpsound,pan((int32_t)x));
20825 hidden_entrance(0,true,false);
20826 didstrig = true;
20827 }
20828 }
20829 else
20830 {
20831 if(!didstrig)
20832 {
20833 stepsecret = ((int32_t)(y+i)&0xF0)+((int32_t)(x+j)>>4);
20834 bool only16_31 = get_bit(quest_rules,qr_STEPTEMP_SECRET_ONLY_16_31)?true:false;
20835 hidden_entrance(0,true,only16_31);
20836 didstrig = true;
20837 //play trigger sound
20838 //int32_t thesfx = combobuf[MAPCOMBO(x+j,y+i)].attribytes[0];
20839 //zprint("Step Secrets SFX: %d\n", thesfx);
20840 //sfx(thesfx,pan((int32_t)x));
20841 sfx(warpsound,pan((int32_t)x));
20842 }
20843 }
20844 }
20845 8604 }
20846 1434 }
20847
20848 717 bool RaftPass = false;//Special case for the raft, where only the raft stuff gets checked and nothing else.
20849
20850 // check if he's standing on a warp he just came out of
20851 // But if the QR is checked, it uses the old logic, cause some quests like Ballad of a Bloodline warp you onto a trigger and this new logic bricks that.
20852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 717 times.
717 if (!get_bit(quest_rules,qr_210_WARPRETURN))
20853 {
20854
6/6
✓ Branch 0 taken 715 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 240 times.
✓ Branch 3 taken 475 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 239 times.
717 if(((int32_t)y>=warpy-8&&(int32_t)y<=warpy+7)&&warpy!=-1)
20855 {
20856
3/6
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 239 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 239 times.
239 if(((int32_t)x>=warpx-8&&(int32_t)x<=warpx+7)&&warpx!=-1)
20857 {
20858
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 239 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
239 if (get_bit(quest_rules, qr_BETTER_RAFT_2) && dir != up) RaftPass = true;
20859 239 else return;
20860 }
20861 }
20862 478 }
20863 else
20864 {
20865 if((int(y)&0xF8)==warpy)
20866 {
20867 if(x==warpx)
20868 {
20869 if (get_bit(quest_rules, qr_BETTER_RAFT_2) && dir != up) RaftPass = true;
20870 else return;
20871 }
20872 }
20873 }
20874
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
478 if (!RaftPass) warpy=-1;
20875
20876
5/6
✓ Branch 0 taken 476 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 475 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
478 if(((int32_t)y<raftwarpy-(get_bit(quest_rules, qr_BETTER_RAFT_2)?12:8)||(int32_t)y>raftwarpy+(get_bit(quest_rules, qr_BETTER_RAFT_2)?3:7))||raftwarpy==-1)
20877 {
20878 478 raftwarpy = -1;
20879 478 }
20880
6/6
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 458 times.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 2 times.
478 if (((int32_t)x<raftwarpx - 8 || (int32_t)x>raftwarpx + 7) || raftwarpx == -1)
20881 {
20882 461 raftwarpx = -1;
20883 461 }
20884 478 int32_t tx=x;
20885 478 int32_t ty=y;
20886
20887 478 int32_t flag=0;
20888 478 int32_t flag2=0;
20889 478 int32_t flag3=0;
20890 478 int32_t type=0;
20891 478 int32_t water=0;
20892 478 int32_t index = 0;
20893
20894 478 bool setsave=false;
20895 478 int32_t warpsfx2 = 0;
20896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
478 if (RaftPass) goto RaftingStuff;
20897
20898 //bool gotpit=false;
20899
20900 int32_t x1,x2,y1,y2;
20901 478 x1 = tx;
20902 478 x2 = tx+15;
20903 478 y1 = ty;
20904 478 y2 = ty+15;
20905
20906
2/4
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 478 times.
478 if((diagonalMovement||NO_GRIDLOCK))
20907 {
20908 x1 = tx+4;
20909 x2 = tx+11;
20910 y1 = ty+4;
20911 y2 = ty+11;
20912 }
20913
20914 int32_t types[4];
20915 478 types[0]=types[1]=types[2]=types[3]=-1;
20916 int32_t cids[4];
20917 int32_t ffcids[4];
20918 478 cids[0]=cids[1]=cids[2]=cids[3]=-1;
20919 478 ffcids[0]=ffcids[1]=ffcids[2]=ffcids[3]=-1;
20920 //
20921 // First, let's find flag1 (combo flag), flag2 (inherent flag) and flag3 (FFC flag)...
20922 //
20923 478 types[0] = MAPFLAG(x1,y1);
20924 478 types[1] = MAPFLAG(x1,y2);
20925 478 types[2] = MAPFLAG(x2,y1);
20926 478 types[3] = MAPFLAG(x2,y2);
20927
20928
20929 //MAPFFCOMBO
20930
20931
20932
3/6
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 478 times.
478 if(types[0]==types[1]&&types[2]==types[3]&&types[1]==types[2])
20933 478 flag = types[0];
20934
20935 // 2.10 compatibility...
20936 else if(y.getInt()%16==8 && types[0]==types[2] && (types[0]==mfFAIRY || types[0]==mfMAGICFAIRY || types[0]==mfALLFAIRY))
20937 flag = types[0];
20938
20939
20940 478 types[0] = MAPCOMBOFLAG(x1,y1);
20941 478 types[1] = MAPCOMBOFLAG(x1,y2);
20942 478 types[2] = MAPCOMBOFLAG(x2,y1);
20943 478 types[3] = MAPCOMBOFLAG(x2,y2);
20944
20945
3/6
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 478 times.
478 if(types[0]==types[1]&&types[2]==types[3]&&types[1]==types[2])
20946 478 flag2 = types[0];
20947
20948 478 types[0] = MAPFFCOMBOFLAG(x1,y1);
20949 478 types[1] = MAPFFCOMBOFLAG(x1,y2);
20950 478 types[2] = MAPFFCOMBOFLAG(x2,y1);
20951 478 types[3] = MAPFFCOMBOFLAG(x2,y2);
20952
20953
20954 //
20955
20956
3/6
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 478 times.
478 if(types[0]==types[1]&&types[2]==types[3]&&types[1]==types[2])
20957 478 flag3 = types[0];
20958
20959 //
20960 // Now, let's check for warp combos...
20961 //
20962
20963 //
20964
20965 478 cids[0] = MAPCOMBO(x1,y1);
20966 478 cids[1] = MAPCOMBO(x1,y2);
20967 478 cids[2] = MAPCOMBO(x2,y1);
20968 478 cids[3] = MAPCOMBO(x2,y2);
20969
20970 478 types[0] = COMBOTYPE(x1,y1);
20971
20972
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(MAPFFCOMBO(x1,y1))
20973 {
20974 types[0] = FFCOMBOTYPE(x1,y1);
20975 cids[0] = MAPFFCOMBO(x1,y1);
20976 }
20977
20978 478 types[1] = COMBOTYPE(x1,y2);
20979
20980
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(MAPFFCOMBO(x1,y2))
20981 {
20982 types[1] = FFCOMBOTYPE(x1,y2);
20983 cids[1] = MAPFFCOMBO(x1,y2);
20984 }
20985
20986 478 types[2] = COMBOTYPE(x2,y1);
20987
20988
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(MAPFFCOMBO(x2,y1))
20989 {
20990 types[2] = FFCOMBOTYPE(x2,y1);
20991 cids[2] = MAPFFCOMBO(x2,y1);
20992 }
20993 478 types[3] = COMBOTYPE(x2,y2);
20994
20995
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(MAPFFCOMBO(x2,y2))
20996 {
20997 types[3] = FFCOMBOTYPE(x2,y2);
20998 cids[3] = MAPFFCOMBO(x2,y2);
20999 }
21000 // Change B, C and D warps into A, for the comparison below...
21001
2/2
✓ Branch 0 taken 1912 times.
✓ Branch 1 taken 478 times.
2390 for(int32_t i=0; i<4; i++)
21002 {
21003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 if(combobuf[cids[i]].triggerflags[0] & combotriggerONLYGENTRIG)
21004 {
21005 types[i] = cNONE;
21006 continue;
21007 }
21008
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1903 times.
1912 if(types[i]==cCAVE)
21009 {
21010 9 index=0;
21011 9 warpsfx2 = combobuf[cids[i]].attribytes[0];
21012 9 }
21013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1903 times.
1903 else if(types[i]==cCAVEB)
21014 {
21015 types[i]=cCAVE;
21016 index=1;
21017 warpsfx2 = combobuf[cids[i]].attribytes[0];
21018 }
21019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1903 times.
1903 else if(types[i]==cCAVEC)
21020 {
21021 types[i]=cCAVE;
21022 index=2;
21023 warpsfx2 = combobuf[cids[i]].attribytes[0];
21024 }
21025
1/2
✓ Branch 0 taken 1903 times.
✗ Branch 1 not taken.
1903 else if(types[i]==cCAVED)
21026 {
21027 types[i]=cCAVE;
21028 index=3;
21029 warpsfx2 = combobuf[cids[i]].attribytes[0];
21030 }
21031
21032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 if(types[i]==cPIT)
21033 {
21034 index=0;
21035 warpsfx2 = combobuf[cids[i]].attribytes[0];
21036 }
21037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cPITB)
21038 {
21039 types[i]=cPIT;
21040 warpsfx2 = combobuf[cids[i]].attribytes[0];
21041 index=1;
21042 }
21043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cPITC)
21044 {
21045 types[i]=cPIT;
21046 warpsfx2 = combobuf[cids[i]].attribytes[0];
21047 index=2;
21048 }
21049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cPITD)
21050 {
21051 types[i]=cPIT;
21052 warpsfx2 = combobuf[cids[i]].attribytes[0];
21053 index=3;
21054 }
21055
1/2
✓ Branch 0 taken 1912 times.
✗ Branch 1 not taken.
1912 else if(types[i]==cPITR)
21056 {
21057 types[i]=cPIT;
21058 warpsfx2 = combobuf[cids[i]].attribytes[0];
21059 index=zc_oldrand()%4;
21060 }
21061
21062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 if(types[i]==cSTAIR)
21063 {
21064 index=0;
21065 warpsfx2 = combobuf[cids[i]].attribytes[0];
21066 }
21067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cSTAIRB)
21068 {
21069 types[i]=cSTAIR;
21070 warpsfx2 = combobuf[cids[i]].attribytes[0];
21071 index=1;
21072 }
21073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cSTAIRC)
21074 {
21075 types[i]=cSTAIR;
21076 warpsfx2 = combobuf[cids[i]].attribytes[0];
21077 index=2;
21078 }
21079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cSTAIRD)
21080 {
21081 types[i]=cSTAIR;
21082 warpsfx2 = combobuf[cids[i]].attribytes[0];
21083 index=3;
21084 }
21085
1/2
✓ Branch 0 taken 1912 times.
✗ Branch 1 not taken.
1912 else if(types[i]==cSTAIRR)
21086 {
21087 types[i]=cSTAIR;
21088 index=zc_oldrand()%4;
21089 warpsfx2 = combobuf[cids[i]].attribytes[0];
21090 }
21091
21092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 if(types[i]==cCAVE2)
21093 {
21094 index=0;
21095 warpsfx2 = combobuf[cids[i]].attribytes[0];
21096 }
21097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cCAVE2B)
21098 {
21099 types[i]=cCAVE2;
21100 index=1;
21101 warpsfx2 = combobuf[cids[i]].attribytes[0];
21102 }
21103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cCAVE2C)
21104 {
21105 types[i]=cCAVE2;
21106 warpsfx2 = combobuf[cids[i]].attribytes[0];
21107 index=2;
21108 }
21109
1/2
✓ Branch 0 taken 1912 times.
✗ Branch 1 not taken.
1912 else if(types[i]==cCAVE2D)
21110 {
21111 types[i]=cCAVE2;
21112 warpsfx2 = combobuf[cids[i]].attribytes[0];
21113 index=3;
21114 }
21115
21116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 if(types[i]==cSWIMWARP)
21117 {
21118 index=0;
21119 warpsfx2 = combobuf[cids[i]].attribytes[0];
21120 }
21121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cSWIMWARPB)
21122 {
21123 types[i]=cSWIMWARP;
21124 warpsfx2 = combobuf[cids[i]].attribytes[0];
21125 index=1;
21126 }
21127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cSWIMWARPC)
21128 {
21129 types[i]=cSWIMWARP;
21130 warpsfx2 = combobuf[cids[i]].attribytes[0];
21131 index=2;
21132 }
21133
1/2
✓ Branch 0 taken 1912 times.
✗ Branch 1 not taken.
1912 else if(types[i]==cSWIMWARPD)
21134 {
21135 types[i]=cSWIMWARP;
21136 warpsfx2 = combobuf[cids[i]].attribytes[0];
21137 index=3;
21138 }
21139
21140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 if(types[i]==cDIVEWARP)
21141 {
21142 index=0;
21143 warpsfx2 = combobuf[cids[i]].attribytes[0];
21144 }
21145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cDIVEWARPB)
21146 {
21147 types[i]=cDIVEWARP;
21148 warpsfx2 = combobuf[cids[i]].attribytes[0];
21149 index=1;
21150 }
21151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cDIVEWARPC)
21152 {
21153 types[i]=cDIVEWARP;
21154 warpsfx2 = combobuf[cids[i]].attribytes[0];
21155 index=2;
21156 }
21157
1/2
✓ Branch 0 taken 1912 times.
✗ Branch 1 not taken.
1912 else if(types[i]==cDIVEWARPD)
21158 {
21159 types[i]=cDIVEWARP;
21160 warpsfx2 = combobuf[cids[i]].attribytes[0];
21161 index=3;
21162 }
21163
21164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 if(types[i]==cSTEP) warpsfx2 = combobuf[cids[i]].attribytes[0];
21165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cSTEPSAME) { types[i]=cSTEP; warpsfx2 = combobuf[cids[i]].attribytes[0];}
21166
1/2
✓ Branch 0 taken 1912 times.
✗ Branch 1 not taken.
1912 else if(types[i]==cSTEPALL) { types[i]=cSTEP; warpsfx2 = combobuf[cids[i]].attribytes[0]; }
21167 1912 }
21168
21169 // Special case for step combos; otherwise, they act oddly in some cases
21170
4/8
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 475 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
478 if((types[0]==types[1]&&types[2]==types[3]&&types[1]==types[2])||(types[1]==cSTEP&&types[3]==cSTEP))
21171 {
21172
3/8
✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 475 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 475 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
475 if(action!=freeze&&action!=sideswimfreeze&&(!msg_active || !get_bit(quest_rules,qr_MSGFREEZE)))
21173 475 type = types[1];
21174 475 }
21175
21176 //Generic Step
21177
3/8
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 478 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
478 if(action!=freeze&&action!=sideswimfreeze&&(!msg_active || !get_bit(quest_rules,qr_MSGFREEZE)))
21178 {
21179 int32_t poses[4];
21180 int32_t sensPoses[4];
21181
2/4
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 478 times.
478 if(diagonalMovement||NO_GRIDLOCK)
21182 getPoses(poses, tx+4, ty+4, tx+11, ty+11);
21183 478 else getPoses(poses, tx, ty, tx+15, ty+15);
21184 478 getPoses(sensPoses, tx, ty+(bigHitbox?0:8), tx+15, ty+15);
21185 478 bool hasStep[4] = {false};
21186
2/2
✓ Branch 0 taken 1912 times.
✓ Branch 1 taken 478 times.
2390 for(auto p = 0; p < 4; ++p)
21187 {
21188
2/2
✓ Branch 0 taken 1912 times.
✓ Branch 1 taken 13384 times.
15296 for(auto lyr = 0; lyr < 7; ++lyr)
21189 {
21190
2/2
✓ Branch 0 taken 8491 times.
✓ Branch 1 taken 4893 times.
13384 newcombo const* cmb = poses[p]<0 ? nullptr : &combobuf[FFCore.tempScreens[lyr]->data[poses[p]]];
21191
3/4
✓ Branch 0 taken 8491 times.
✓ Branch 1 taken 4893 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13384 times.
13384 if((cmb && (cmb->triggerflags[0] & (combotriggerSTEP|combotriggerSTEPSENS)))
21192 13384 || types[p] == cSTEP)
21193 {
21194 hasStep[p] = true;
21195 break;
21196 }
21197 13384 }
21198 1912 }
21199 478 bool canNormalStep = true;
21200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
478 for(auto p = 0; p < 4; ++p)
21201 {
21202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
478 if(poses[p] < 0) continue;
21203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
478 if(!hasStep[p])
21204 {
21205 478 canNormalStep = false;
21206 478 break;
21207 }
21208 }
21209
2/2
✓ Branch 0 taken 1912 times.
✓ Branch 1 taken 478 times.
2390 for(auto p = 0; p < 4; ++p)
21210 {
21211
2/2
✓ Branch 0 taken 13384 times.
✓ Branch 1 taken 1912 times.
15296 for(auto lyr = 0; lyr < 7; ++lyr)
21212 {
21213
2/2
✓ Branch 0 taken 8491 times.
✓ Branch 1 taken 4893 times.
13384 newcombo const* cmb = poses[p]<0 ? nullptr : &combobuf[FFCore.tempScreens[lyr]->data[poses[p]]];
21214
2/2
✓ Branch 0 taken 5250 times.
✓ Branch 1 taken 8134 times.
13384 newcombo const* cmb2 = sensPoses[p]<0 ? nullptr : &combobuf[FFCore.tempScreens[lyr]->data[sensPoses[p]]];
21215
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 13384 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
13384 if(canNormalStep && cmb && (cmb->triggerflags[0] & combotriggerSTEP))
21216 {
21217 do_trigger_combo(lyr,poses[p]);
21218 if(poses[p] == sensPoses[p]) continue;
21219 }
21220
3/4
✓ Branch 0 taken 5250 times.
✓ Branch 1 taken 8134 times.
✓ Branch 2 taken 5250 times.
✗ Branch 3 not taken.
13384 if(cmb2 && (cmb2->triggerflags[0] & combotriggerSTEPSENS))
21221 {
21222 do_trigger_combo(lyr,sensPoses[p]);
21223 }
21224 13384 }
21225 1912 }
21226 478 }
21227
21228 //
21229 // Now, let's check for Save combos...
21230 //
21231 478 x1 = tx+4;
21232 478 x2 = tx+11;
21233 478 y1 = ty+4;
21234 478 y2 = ty+11;
21235
21236 478 types[0] = COMBOTYPE(x1,y1);
21237 478 cids[0] = MAPCOMBO(x1,y1);
21238
21239
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(MAPFFCOMBO(x1,y1))
21240 {
21241 types[0] = FFCOMBOTYPE(x1,y1);
21242 cids[0] = MAPFFCOMBO(x1,y1);
21243 }
21244
21245 478 types[1] = COMBOTYPE(x1,y2);
21246 478 cids[1] = MAPCOMBO(x1,y2);
21247
21248
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(MAPFFCOMBO(x1,y2))
21249 {
21250 types[1] = FFCOMBOTYPE(x1,y2);
21251 cids[1] = MAPFFCOMBO(x1,y2);
21252 }
21253
21254 478 types[2] = COMBOTYPE(x2,y1);
21255 478 cids[2] = MAPCOMBO(x2,y1);
21256
21257
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(MAPFFCOMBO(x2,y1))
21258 {
21259 types[2] = FFCOMBOTYPE(x2,y1);
21260 cids[2] = MAPFFCOMBO(x2,y1);
21261 }
21262
21263 478 types[3] = COMBOTYPE(x2,y2);
21264 478 cids[3] = MAPCOMBO(x2,y2);
21265
21266
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(MAPFFCOMBO(x2,y2))
21267 {
21268 types[3] = FFCOMBOTYPE(x2,y2);
21269 cids[3] = MAPFFCOMBO(x2,y2);
21270 }
21271
21272
21273
2/2
✓ Branch 0 taken 478 times.
✓ Branch 1 taken 1912 times.
2390 for(int32_t i=0; i<4; i++)
21274 {
21275
1/2
✓ Branch 0 taken 1912 times.
✗ Branch 1 not taken.
1912 if(combobuf[cids[i]].triggerflags[0] & combotriggerONLYGENTRIG)
21276 {
21277 if(types[i] == cSAVE || types[i] == cSAVE2)
21278 {
21279 types[i] = cNONE;
21280 setsave = false;
21281 break;
21282 }
21283 }
21284
1/2
✓ Branch 0 taken 1912 times.
✗ Branch 1 not taken.
1912 if(types[i]==cSAVE) setsave=true;
21285
21286
1/2
✓ Branch 0 taken 1912 times.
✗ Branch 1 not taken.
1912 if(types[i]==cSAVE2) setsave=true;
21287 1912 }
21288
21289
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
478 if(setsave && types[0]==types[1]&&types[2]==types[3]&&types[1]==types[2])
21290 {
21291 last_savepoint_id = cids[0];
21292 type = types[0];
21293 }
21294 //
21295 // Now, let's check for Drowning combos...
21296 //
21297
2/4
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 478 times.
478 if(get_bit(quest_rules,qr_DROWN) || CanSideSwim())
21298 {
21299 y1 = ty+9;
21300 y2 = ty+15;
21301 if (get_bit(quest_rules, qr_SMARTER_WATER))
21302 {
21303 if (iswaterex(0, currmap, currscr, -1, x1, y1, true, false) &&
21304 iswaterex(0, currmap, currscr, -1, x1, y2, true, false) &&
21305 iswaterex(0, currmap, currscr, -1, x2, y1, true, false) &&
21306 iswaterex(0, currmap, currscr, -1, x2, y2, true, false)) water = iswaterex(0, currmap, currscr, -1, (x2+x1)/2,(y2+y1)/2, true, false);
21307 }
21308 else
21309 {
21310 types[0] = COMBOTYPE(x1,y1);
21311
21312 if(MAPFFCOMBO(x1,y1))
21313 types[0] = FFCOMBOTYPE(x1,y1);
21314
21315 types[1] = COMBOTYPE(x1,y2);
21316
21317 if(MAPFFCOMBO(x1,y2))
21318 types[1] = FFCOMBOTYPE(x1,y2);
21319
21320 types[2] = COMBOTYPE(x2,y1);
21321
21322 if(MAPFFCOMBO(x2,y1))
21323 types[2] = FFCOMBOTYPE(x2,y1);
21324
21325 types[3] = COMBOTYPE(x2,y2);
21326
21327 if(MAPFFCOMBO(x2,y2))
21328 types[3] = FFCOMBOTYPE(x2,y2);
21329
21330 int32_t typec = COMBOTYPE((x2+x1)/2,(y2+y1)/2);
21331 if(MAPFFCOMBO((x2+x1)/2,(y2+y1)/2))
21332 typec = FFCOMBOTYPE((x2+x1)/2,(y2+y1)/2);
21333
21334 if(combo_class_buf[types[0]].water && combo_class_buf[types[1]].water &&
21335 combo_class_buf[types[2]].water && combo_class_buf[types[3]].water && combo_class_buf[typec].water)
21336 water = typec;
21337 }
21338 }
21339
21340
21341 // Pits have a bigger 'hitbox' than stairs...
21342 478 x1 = tx+7;
21343 478 x2 = tx+8;
21344 478 y1 = ty+7+(bigHitbox?0:4);
21345 478 y2 = ty+8+(bigHitbox?0:4);
21346
21347 478 types[0] = COMBOTYPE(x1,y1);
21348 478 cids[0] = MAPCOMBO(x1,y1);
21349
21350
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(MAPFFCOMBO(x1,y1))
21351 {
21352 types[0] = FFCOMBOTYPE(x1,y1);
21353 cids[0] = MAPFFCOMBO(x1,y1);
21354 }
21355
21356 478 types[1] = COMBOTYPE(x1,y2);
21357 478 cids[1] = MAPCOMBO(x1,y2);
21358
21359
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(MAPFFCOMBO(x1,y2))
21360 {
21361 types[1] = FFCOMBOTYPE(x1,y2);
21362 cids[1] = MAPFFCOMBO(x1,y2);
21363 }
21364 478 types[2] = COMBOTYPE(x2,y1);
21365 478 cids[2] = MAPCOMBO(x2,y1);
21366
21367
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(MAPFFCOMBO(x2,y1))
21368 {
21369 types[2] = FFCOMBOTYPE(x2,y1);
21370 cids[2] = MAPFFCOMBO(x2,y1);
21371 }
21372
21373 478 types[3] = COMBOTYPE(x2,y2);
21374 478 cids[3] = MAPCOMBO(x2,y2);
21375
21376
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(MAPFFCOMBO(x2,y2))
21377 {
21378 types[3] = FFCOMBOTYPE(x2,y2);
21379 cids[3] = MAPFFCOMBO(x2,y2);
21380 }
21381
21382
2/2
✓ Branch 0 taken 1912 times.
✓ Branch 1 taken 478 times.
2390 for(int32_t i=0; i<4; i++)
21383 {
21384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 if(combobuf[cids[i]].triggerflags[0] & combotriggerONLYGENTRIG)
21385 {
21386 types[i] = cNONE;
21387 continue;
21388 }
21389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 if(types[i]==cPIT)
21390 {
21391 index=0;
21392 warpsfx2 = combobuf[cids[i]].attribytes[0];
21393 }
21394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cPITB)
21395 {
21396 types[i]=cPIT;
21397 index=1;
21398 warpsfx2 = combobuf[cids[i]].attribytes[0];
21399 }
21400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1912 times.
1912 else if(types[i]==cPITC)
21401 {
21402 types[i]=cPIT;
21403 index=2;
21404 warpsfx2 = combobuf[cids[i]].attribytes[0];
21405 }
21406
1/2
✓ Branch 0 taken 1912 times.
✗ Branch 1 not taken.
1912 else if(types[i]==cPITD)
21407 {
21408 types[i]=cPIT;
21409 index=3;
21410 warpsfx2 = combobuf[cids[i]].attribytes[0];
21411 }
21412 1912 }
21413
21414
4/8
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 478 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 478 times.
478 if(types[0]==cPIT||types[1]==cPIT||types[2]==cPIT||types[3]==cPIT)
21415 if(action!=freeze&&action!=sideswimfreeze&& (!msg_active || !get_bit(quest_rules,qr_MSGFREEZE)))
21416 type=cPIT;
21417
21418 //
21419 // Time to act on our results for type, flag, flag2 and flag3...
21420 //
21421
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
478 if(type==cSAVE&&currscr<128)
21422 *ls=1;
21423
21424
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
478 if(type==cSAVE2&&currscr<128)
21425 *ls=2;
21426
21427
4/8
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 478 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 478 times.
478 if(refilling==REFILL_LIFE || flag==mfFAIRY||flag2==mfFAIRY||flag3==mfFAIRY)
21428 {
21429 fairycircle(REFILL_LIFE);
21430
21431 if(fairyclk!=0) return;
21432 }
21433
21434
4/8
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 478 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 478 times.
478 if(refilling==REFILL_MAGIC || flag==mfMAGICFAIRY||flag2==mfMAGICFAIRY||flag3==mfMAGICFAIRY)
21435 {
21436 fairycircle(REFILL_MAGIC);
21437
21438 if(fairyclk!=0) return;
21439 }
21440
21441
4/8
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 478 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 478 times.
478 if(refilling==REFILL_ALL || flag==mfALLFAIRY||flag2==mfALLFAIRY||flag3==mfALLFAIRY)
21442 {
21443 fairycircle(REFILL_ALL);
21444
21445 if(fairyclk!=0) return;
21446 }
21447
21448 // Just in case Hero was moved off of the fairy flag
21449
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if(refilling==REFILL_FAIRYDONE)
21450 {
21451 fairycircle(REFILL_NONE);
21452
21453 if(fairyclk!=0) return;
21454 }
21455
21456
4/8
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 478 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 478 times.
478 if(flag==mfZELDA||flag2==mfZELDA||flag3==mfZELDA || combo_class_buf[type].win_game)
21457 {
21458 attackclk = 0; //get rid of Hero's sword if it was stuck out, charged.
21459 win_game();
21460 return;
21461 }
21462
21463
2/4
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
478 if((z>0 || fakez>0) && !(tmpscr->flags2&fAIRCOMBOS))
21464 return;
21465
21466
2/4
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 478 times.
478 if((type==cTRIGNOFLAG || type==cTRIGFLAG))
21467 {
21468
21469 if((((ty+8)&0xF0)+((tx+8)>>4))!=stepsecret || get_bit(quest_rules,qr_TRIGGERSREPEAT))
21470 {
21471 stepsecret = (((ty+8)&0xF0)+((tx+8)>>4));
21472 sfx(combobuf[tmpscr->data[stepsecret]].attribytes[0],pan((int32_t)x));
21473 //zprint("Step Secrets Sound: %d\n", combobuf[tmpscr->data[stepsecret]].attribytes[0]);
21474
21475 if(type==cTRIGFLAG && canPermSecret())
21476 {
21477 if(!(tmpscr->flags5&fTEMPSECRETS)) setmapflag(mSECRET);
21478
21479 hidden_entrance(0,true,false);
21480 }
21481 else
21482 {
21483 bool only16_31 = get_bit(quest_rules,qr_STEPTEMP_SECRET_ONLY_16_31)?true:false;
21484 hidden_entrance(0,true,only16_31);
21485 }
21486 }
21487 }
21488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
478 else if(!didstrig)
21489 {
21490 478 stepsecret = -1;
21491 478 }
21492
21493 //Better? Dock collision
21494
21495 // Drown if:
21496 // * Water (obviously walkable),
21497 // * Quest Rule allows it,
21498 // * Not on stepladder,
21499 // * Not jumping,
21500 // * Not hovering,
21501 // * Not rafting,
21502 // * Not swallowed,
21503 // * Not a dried lake.
21504
21505 // This used to check for swimming too, but I moved that into the block so that you can drown in higher-leveled water. -Dimi
21506
21507
1/22
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
478 if(water > 0 && ((get_bit(quest_rules,qr_DROWN) && z==0 && fakez==0 && fall>=0 && fakefall>=0) || CanSideSwim()) && !ladderx && hoverclk==0 && action!=rafting && !inlikelike && !DRIEDLAKE)
21508 {
21509 if(current_item(itype_flippers) <= 0 || current_item(itype_flippers) < combobuf[water].attribytes[0] || ((combobuf[water].usrflags&cflag1) && !(itemsbuf[current_item_id(itype_flippers)].flags & ITEM_FLAG3)))
21510 {
21511 if(!(ladderx+laddery)) drownCombo = water;
21512 if (combobuf[water].usrflags&cflag1) Drown(1);
21513 else Drown();
21514 if(byte drown_sfx = combobuf[water].attribytes[4])
21515 sfx(drown_sfx, pan(int32_t(x)));
21516 }
21517 else if (!isSwimming())
21518 {
21519 SetSwim();
21520 if (!IsSideSwim()) attackclk = charging = spins = 0;
21521 landswim=0;
21522 return;
21523 }
21524 }
21525
21526
21527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
478 if(type==cSTEP)
21528 {
21529 //zprint2("Hero.HasHeavyBoots(): is: %s\n", ( (Hero.HasHeavyBoots()) ? "true" : "false" ));
21530 if((((ty+8)&0xF0)+((tx+8)>>4))!=stepnext)
21531 {
21532 stepnext=((ty+8)&0xF0)+((tx+8)>>4);
21533
21534 if
21535 (
21536 COMBOTYPE(tx+8,ty+8)==cSTEP && /*required item*/
21537 (!combobuf[tmpscr->data[stepnext]].attribytes[1] || (combobuf[tmpscr->data[stepnext]].attribytes[1] && game->item[combobuf[tmpscr->data[stepnext]].attribytes[1]]) )
21538 && /*HEAVY*/
21539 ( ( !(combobuf[tmpscr->data[stepnext]].usrflags&cflag1) ) || ((combobuf[tmpscr->data[stepnext]].usrflags&cflag1) && Hero.HasHeavyBoots() ) )
21540 )
21541
21542 {
21543 sfx(combobuf[tmpscr->data[stepnext]].attribytes[0],pan((int32_t)x));
21544 tmpscr->data[stepnext]++;
21545
21546 }
21547
21548 if
21549 (
21550 COMBOTYPE(tx+8,ty+8)==cSTEPSAME && /*required item*/
21551 (!combobuf[MAPCOMBO(tx+8,ty+8)].attribytes[1] || (combobuf[MAPCOMBO(tx+8,ty+8)].attribytes[1] && game->item[combobuf[MAPCOMBO(tx+8,ty+8)].attribytes[1]]) )
21552 && /*HEAVY*/
21553 ( ( !(combobuf[tmpscr->data[stepnext]].usrflags&cflag1) ) || ((combobuf[tmpscr->data[stepnext]].usrflags&cflag1) && Hero.HasHeavyBoots() ) )
21554 )
21555 {
21556 int32_t stepc = tmpscr->data[stepnext];
21557 sfx(combobuf[MAPCOMBO(tx+8,ty+8)].attribytes[0],pan((int32_t)x));
21558 for(int32_t k=0; k<176; k++)
21559 {
21560 if(tmpscr->data[k]==stepc)
21561 {
21562 tmpscr->data[k]++;
21563 }
21564 }
21565 }
21566
21567 if
21568 (
21569 COMBOTYPE(tx+8,ty+8)==cSTEPALL && /*required item*/
21570 (!combobuf[MAPCOMBO(tx+8,ty+8)].attribytes[1] || (combobuf[MAPCOMBO(tx+8,ty+8)].attribytes[1] && game->item[combobuf[MAPCOMBO(tx+8,ty+8)].attribytes[1]]) )
21571 && /*HEAVY*/
21572 ( ( !(combobuf[tmpscr->data[stepnext]].usrflags&cflag1) ) || ((combobuf[tmpscr->data[stepnext]].usrflags&cflag1) && Hero.HasHeavyBoots() ) )
21573 )
21574 {
21575 sfx(combobuf[MAPCOMBO(tx+8,ty+8)].attribytes[0],pan((int32_t)x));
21576 for(int32_t k=0; k<176; k++)
21577 {
21578 if(
21579 (combobuf[tmpscr->data[k]].type==cSTEP)||
21580 (combobuf[tmpscr->data[k]].type==cSTEPSAME)||
21581 (combobuf[tmpscr->data[k]].type==cSTEPALL)||
21582 (combobuf[tmpscr->data[k]].type==cSTEPCOPY)
21583 )
21584 {
21585 tmpscr->data[k]++;
21586 }
21587 }
21588 }
21589 }
21590 }
21591
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
478 else if(type==cSTEPSFX && action == walking)
21592 {
21593 trigger_stepfx(0, COMBOPOS(tx+8,ty+8), true);
21594 }
21595 478 else stepnext = -1;
21596
21597 478 detail_int[0]=tx;
21598 478 detail_int[1]=ty;
21599
21600
21601
5/8
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 477 times.
✓ Branch 4 taken 477 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
478 if(!((type==cCAVE || type==cCAVE2) && z==0 && fakez==0) && type!=cSTAIR &&
21602
3/6
✓ Branch 0 taken 477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 477 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 477 times.
✗ Branch 5 not taken.
477 type!=cPIT && type!=cSWIMWARP && type!=cRESET &&
21603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
477 !(type==cDIVEWARP && isDiving()))
21604 477 {
21605 RaftingStuff:
21606
1/2
✓ Branch 0 taken 477 times.
✗ Branch 1 not taken.
477 if (get_bit(quest_rules, qr_BETTER_RAFT_2))
21607 {
21608 bool doraft = true;
21609 if(((int32_t)y>=raftwarpy-12&&(int32_t)y<=raftwarpy+3)&&raftwarpy!=-1)
21610 {
21611 if(((int32_t)x>=raftwarpx-8&&(int32_t)x<=raftwarpx+7)&&raftwarpx!=-1)
21612 {
21613 doraft = false;
21614 }
21615 }
21616 //if (mfRAFT)
21617 int32_t rafttypes[2];
21618 int32_t raftx1 = tx+6;
21619 int32_t raftx2 = tx+9;
21620 int32_t rafty = ty+11;
21621 int32_t raftflags[3];
21622 rafttypes[0]=rafttypes[1]=-1;
21623 raftflags[0]=raftflags[1]=raftflags[2]=0;
21624 rafttypes[0] = MAPFLAG(raftx1,rafty);
21625 rafttypes[1] = MAPFLAG(raftx2,rafty);
21626
21627 if(rafttypes[0]==rafttypes[1])
21628 raftflags[0] = rafttypes[0];
21629
21630
21631 rafttypes[0] = MAPCOMBOFLAG(raftx1,rafty);
21632 rafttypes[1] = MAPCOMBOFLAG(raftx2,rafty);
21633
21634 if(rafttypes[0]==rafttypes[1])
21635 raftflags[1] = rafttypes[0];
21636
21637 rafttypes[0] = MAPFFCOMBOFLAG(raftx1,rafty);
21638 rafttypes[1] = MAPFFCOMBOFLAG(raftx2,rafty);
21639
21640 if(rafttypes[0]==rafttypes[1])
21641 raftflags[2] = rafttypes[0];
21642
21643 for (int32_t m = 0; m < 3; ++m)
21644 {
21645 if (raftflags[m] == mfRAFT || raftflags[m] == mfRAFT_BRANCH)
21646 {
21647 if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && action!=sideswimhit && z==0 && fakez==0 && (combo_class_buf[COMBOTYPE(tx+8, ty+11)].dock || combo_class_buf[FFCOMBOTYPE(tx+8, ty+11)].dock))
21648 {
21649 if((isRaftFlag(nextflag(tx,ty+11,dir,false))||isRaftFlag(nextflag(tx,ty+11,dir,true))))
21650 {
21651 reset_swordcharge();
21652 action=rafting; FFCore.setHeroAction(rafting);
21653 raftclk=0;
21654 if (get_bit(quest_rules, qr_RAFT_SOUND)) sfx(itemsbuf[current_item_id(itype_raft)].usesound,pan(x.getInt()));
21655 else sfx(tmpscr->secretsfx);
21656 }
21657 else if (get_bit(quest_rules, qr_BETTER_RAFT) && doraft)
21658 {
21659 for (int32_t i = 0; i < 4; ++i)
21660 {
21661 if(isRaftFlag(nextflag(GridX(tx+8),GridY(ty+11),i,false))||isRaftFlag(nextflag(GridX(tx+8),GridY(ty+11),i,true)))
21662 {
21663 reset_swordcharge();
21664 action=rafting; FFCore.setHeroAction(rafting);
21665 raftclk=0;
21666 if (get_bit(quest_rules, qr_RAFT_SOUND)) sfx(itemsbuf[current_item_id(itype_raft)].usesound,pan(x.getInt()));
21667 else sfx(tmpscr->secretsfx);
21668 dir = i;
21669 break;
21670 }
21671 }
21672 }
21673 }
21674 }
21675 }
21676 }
21677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
477 if (RaftPass) return;
21678
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
✗ Branch 2 not taken.
477 switch(flag)
21679 {
21680 case mfDIVE_ITEM:
21681 if(isDiving() && (!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN)))
21682 {
21683 additem(x, y, tmpscr->catchall,
21684 ipONETIME2 | ipBIGRANGE | ipHOLDUP | ipNODRAW | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0));
21685 sfx(tmpscr->secretsfx);
21686 }
21687
21688 return;
21689
21690 case mfRAFT:
21691 case mfRAFT_BRANCH:
21692
21693 // if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && type==cOLD_DOCK)
21694 if (!get_bit(quest_rules, qr_BETTER_RAFT_2))
21695 {
21696 bool doraft = true;
21697 if(((int32_t)y>=raftwarpy-8&&(int32_t)y<=raftwarpy+7)&&raftwarpy!=-1)
21698 {
21699 if(((int32_t)x>=raftwarpx-8&&(int32_t)x<=raftwarpx+7)&&raftwarpx!=-1)
21700 {
21701 doraft = false;
21702 }
21703 }
21704 if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && action!=sideswimhit && z==0 && fakez==0 && combo_class_buf[type].dock)
21705 {
21706 if(isRaftFlag(nextflag(tx,ty,dir,false))||isRaftFlag(nextflag(tx,ty,dir,true)))
21707 {
21708 reset_swordcharge();
21709 action=rafting; FFCore.setHeroAction(rafting);
21710 raftclk=0;
21711 if (get_bit(quest_rules, qr_RAFT_SOUND)) sfx(itemsbuf[current_item_id(itype_raft)].usesound,pan(x.getInt()));
21712 else sfx(tmpscr->secretsfx);
21713 }
21714 else if (get_bit(quest_rules, qr_BETTER_RAFT) && doraft)
21715 {
21716 for (int32_t i = 0; i < 4; ++i)
21717 {
21718 if(isRaftFlag(nextflag(GridX(tx+8),GridY(ty+8),i,false))||isRaftFlag(nextflag(GridX(tx+8),GridY(ty+8),i,true)))
21719 {
21720 reset_swordcharge();
21721 action=rafting; FFCore.setHeroAction(rafting);
21722 raftclk=0;
21723 if (get_bit(quest_rules, qr_RAFT_SOUND)) sfx(itemsbuf[current_item_id(itype_raft)].usesound,pan(x.getInt()));
21724 else sfx(tmpscr->secretsfx);
21725 dir = i;
21726 break;
21727 }
21728 }
21729 }
21730 }
21731 }
21732
21733 return;
21734
21735 default:
21736 477 break;
21737 //return;
21738 }
21739
21740
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
✗ Branch 2 not taken.
477 switch(flag2)
21741 {
21742 case mfDIVE_ITEM:
21743 if(isDiving() && (!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN)))
21744 {
21745 additem(x, y, tmpscr->catchall,
21746 ipONETIME2 | ipBIGRANGE | ipHOLDUP | ipNODRAW | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0));
21747 sfx(tmpscr->secretsfx);
21748 }
21749
21750 return;
21751
21752 case mfRAFT:
21753 case mfRAFT_BRANCH:
21754
21755 // if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && type==cOLD_DOCK)
21756 if (!get_bit(quest_rules, qr_BETTER_RAFT_2))
21757 {
21758 bool doraft = true;
21759 if(((int32_t)y>=raftwarpy-8&&(int32_t)y<=raftwarpy+7)&&raftwarpy!=-1)
21760 {
21761 if(((int32_t)x>=raftwarpx-8&&(int32_t)x<=raftwarpx+7)&&raftwarpx!=-1)
21762 {
21763 doraft = false;
21764 }
21765 }
21766 if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && action!=sideswimhit && z==0 && fakez==0 && combo_class_buf[type].dock)
21767 {
21768 if((isRaftFlag(nextflag(tx,ty,dir,false))||isRaftFlag(nextflag(tx,ty,dir,true))))
21769 {
21770 reset_swordcharge();
21771 action=rafting; FFCore.setHeroAction(rafting);
21772 raftclk=0;
21773 if (get_bit(quest_rules, qr_RAFT_SOUND)) sfx(itemsbuf[current_item_id(itype_raft)].usesound,pan(x.getInt()));
21774 else sfx(tmpscr->secretsfx);
21775 }
21776 else if (get_bit(quest_rules, qr_BETTER_RAFT) && doraft)
21777 {
21778 for (int32_t i = 0; i < 4; ++i)
21779 {
21780 if(isRaftFlag(nextflag(GridX(tx+8),GridY(ty+8),i,false))||isRaftFlag(nextflag(GridX(tx+8),GridY(ty+8),i,true)))
21781 {
21782 reset_swordcharge();
21783 action=rafting; FFCore.setHeroAction(rafting);
21784 raftclk=0;
21785 if (get_bit(quest_rules, qr_RAFT_SOUND)) sfx(itemsbuf[current_item_id(itype_raft)].usesound,pan(x.getInt()));
21786 else sfx(tmpscr->secretsfx);
21787 dir = i;
21788 break;
21789 }
21790 }
21791 }
21792 }
21793 }
21794
21795 return;
21796
21797 default:
21798 477 break;
21799 //return;
21800 }
21801
21802
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
✗ Branch 2 not taken.
477 switch(flag3)
21803 {
21804 case mfDIVE_ITEM:
21805 if(isDiving() && (!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN)))
21806 {
21807 additem(x, y, tmpscr->catchall,
21808 ipONETIME2 | ipBIGRANGE | ipHOLDUP | ipNODRAW | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0));
21809 sfx(tmpscr->secretsfx);
21810 }
21811
21812 return;
21813
21814 case mfRAFT:
21815 case mfRAFT_BRANCH:
21816
21817 // if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && type==cOLD_DOCK)
21818 if (!get_bit(quest_rules, qr_BETTER_RAFT_2))
21819 {
21820 bool doraft = true;
21821 if(((int32_t)y>=raftwarpy-8&&(int32_t)y<=raftwarpy+7)&&raftwarpy!=-1)
21822 {
21823 if(((int32_t)x>=raftwarpx-8&&(int32_t)x<=raftwarpx+7)&&raftwarpx!=-1)
21824 {
21825 doraft = false;
21826 }
21827 }
21828 if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && action!=sideswimhit && z==0 && fakez==0 && combo_class_buf[type].dock)
21829 {
21830 if((isRaftFlag(nextflag(tx,ty,dir,false))||isRaftFlag(nextflag(tx,ty,dir,true))))
21831 {
21832 reset_swordcharge();
21833 action=rafting; FFCore.setHeroAction(rafting);
21834 raftclk=0;
21835 if (get_bit(quest_rules, qr_RAFT_SOUND)) sfx(itemsbuf[current_item_id(itype_raft)].usesound,pan(x.getInt()));
21836 else sfx(tmpscr->secretsfx);
21837 }
21838 else if (get_bit(quest_rules, qr_BETTER_RAFT) && doraft)
21839 {
21840 for (int32_t i = 0; i < 4; ++i)
21841 {
21842 if(isRaftFlag(nextflag(GridX(tx+8),GridY(ty+8),i,false))||isRaftFlag(nextflag(GridX(tx+8),GridY(ty+8),i,true)))
21843 {
21844 reset_swordcharge();
21845 action=rafting; FFCore.setHeroAction(rafting);
21846 raftclk=0;
21847 if (get_bit(quest_rules, qr_RAFT_SOUND)) sfx(itemsbuf[current_item_id(itype_raft)].usesound,pan(x.getInt()));
21848 else sfx(tmpscr->secretsfx);
21849 dir = i;
21850 break;
21851 }
21852 }
21853 }
21854 }
21855 }
21856
21857 return;
21858
21859 default:
21860 477 return;
21861 }
21862 }
21863
21864
21865 1 int32_t t=(currscr<128)?0:1;
21866
21867
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if((type==cCAVE || type==cCAVE2) && (tmpscr[t].tilewarptype[index]==wtNOWARP)) return;
21868
21869 //don't do this for canceled warps -DD
21870 //I have no idea why we do this skip, but I'll dutifully propagate it to all cases below...
21871 /*if(tmpscr[t].tilewarptype[index] != wtNOWARP)
21872 {
21873 draw_screen(tmpscr);
21874 advanceframe(true);
21875 }*/
21876
21877 1 bool skippedaframe=false;
21878
21879
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if(type==cCAVE || type==cCAVE2 || type==cSTAIR)
21880 {
21881 // Stop music only if:
21882 // * entering a Guy Cave
21883 // * warping to a DMap whose music is different.
21884
21885 1 int32_t tdm = tmpscr[t].tilewarpdmap[index];
21886
21887
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(tmpscr[t].tilewarptype[index]<=wtPASS)
21888 {
21889
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if((DMaps[currdmap].flags&dmfCAVES) && tmpscr[t].tilewarptype[index] == wtCAVE)
21890 1 music_stop();
21891 1 }
21892 else
21893 {
21894 if(zcmusic!=NULL)
21895 {
21896 if(strcmp(zcmusic->filename, DMaps[tdm].tmusic) != 0 ||
21897 (zcmusic->type==ZCMF_GME && zcmusic->track!=DMaps[tdm].tmusictrack))
21898 music_stop();
21899 }
21900 else if(DMaps[tmpscr->tilewarpdmap[index]].midi != (currmidi-ZC_MIDI_COUNT+4) &&
21901 TheMaps[(DMaps[tdm].map*MAPSCRS + (tmpscr[t].tilewarpscr[index] + DMaps[tdm].xoff))].screen_midi != (currmidi-ZC_MIDI_COUNT+4))
21902 music_stop();
21903 }
21904
21905 1 stop_sfx(QMisc.miscsfx[sfxLOWHEART]);
21906
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 bool opening = (tmpscr[t].tilewarptype[index]<=wtPASS && !(DMaps[currdmap].flags&dmfCAVES && tmpscr[t].tilewarptype[index]==wtCAVE)
21907 1 ? false : COOLSCROLL);
21908
21909 1 FFCore.warpScriptCheck();
21910 1 draw_screen(tmpscr);
21911 1 advanceframe(true);
21912
21913 1 skippedaframe=true;
21914
21915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(type==cCAVE2) walkup2(opening);
21916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if(type==cCAVE) walkdown(opening);
21917 1 }
21918
21919
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(type==cPIT)
21920 {
21921 didpit=true;
21922 pitx=x;
21923 pity=y;
21924 warp_sound = warpsfx2;
21925 }
21926
21927
2/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if(DMaps[currdmap].flags&dmf3STAIR && (currscr==129 || !(DMaps[currdmap].flags&dmfGUYCAVES))
21928
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 && tmpscr[specialcave > 0 && DMaps[currdmap].flags&dmfGUYCAVES ? 1:0].room==rWARP && type==cSTAIR)
21929 {
21930 if(!skippedaframe)
21931 {
21932 FFCore.warpScriptCheck();
21933 draw_screen(tmpscr);
21934 advanceframe(true);
21935 }
21936
21937 // "take any road you want"
21938 int32_t dw = x<112 ? 1 : (x>136 ? 3 : 2);
21939 int32_t code = WARPCODE(currdmap,homescr,dw);
21940
21941 if(code>-1)
21942 {
21943 bool changedlevel = false;
21944 bool changeddmap = false;
21945 if(currdmap != code>>8)
21946 {
21947 timeExitAllGenscript(GENSCR_ST_CHANGE_DMAP);
21948 changeddmap = true;
21949 }
21950 if(dlevel != DMaps[code>>8].level)
21951 {
21952 timeExitAllGenscript(GENSCR_ST_CHANGE_LEVEL);
21953 changedlevel = true;
21954 }
21955 currdmap = code>>8;
21956 dlevel = DMaps[currdmap].level;
21957 if(changeddmap)
21958 {
21959 throwGenScriptEvent(GENSCR_EVENT_CHANGE_DMAP);
21960 }
21961 if(changedlevel)
21962 {
21963 throwGenScriptEvent(GENSCR_EVENT_CHANGE_LEVEL);
21964 }
21965
21966 currmap = DMaps[currdmap].map;
21967 homescr = (code&0xFF) + DMaps[currdmap].xoff;
21968 init_dmap();
21969
21970 if(canPermSecret())
21971 setmapflag(mSECRET);
21972 }
21973
21974 if(specialcave==STAIRCAVE) exitcave();
21975
21976 return;
21977 }
21978
21979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(type==cRESET)
21980 {
21981 if(!skippedaframe)
21982 {
21983 FFCore.warpScriptCheck();
21984 draw_screen(tmpscr);
21985 advanceframe(true);
21986 }
21987
21988 if(!(tmpscr->noreset&mSECRET)) unsetmapflag(mSECRET);
21989
21990 if(!(tmpscr->noreset&mITEM)) unsetmapflag(mITEM);
21991
21992 if(!(tmpscr->noreset&mSPECIALITEM)) unsetmapflag(mSPECIALITEM);
21993
21994 if(!(tmpscr->noreset&mNEVERRET)) unsetmapflag(mNEVERRET);
21995
21996 if(!(tmpscr->noreset&mCHEST)) unsetmapflag(mCHEST);
21997
21998 if(!(tmpscr->noreset&mLOCKEDCHEST)) unsetmapflag(mLOCKEDCHEST);
21999
22000 if(!(tmpscr->noreset&mBOSSCHEST)) unsetmapflag(mBOSSCHEST);
22001
22002 if(!(tmpscr->noreset&mLOCKBLOCK)) unsetmapflag(mLOCKBLOCK);
22003
22004 if(!(tmpscr->noreset&mBOSSLOCKBLOCK)) unsetmapflag(mBOSSLOCKBLOCK);
22005
22006 if(isdungeon())
22007 {
22008 if(!(tmpscr->noreset&mDOOR_LEFT)) unsetmapflag(mDOOR_LEFT);
22009
22010 if(!(tmpscr->noreset&mDOOR_RIGHT)) unsetmapflag(mDOOR_RIGHT);
22011
22012 if(!(tmpscr->noreset&mDOOR_DOWN)) unsetmapflag(mDOOR_DOWN);
22013
22014 if(!(tmpscr->noreset&mDOOR_UP)) unsetmapflag(mDOOR_UP);
22015 }
22016
22017 didpit=true;
22018 pitx=x;
22019 pity=y;
22020 sdir=dir;
22021 dowarp(4,0, warpsfx2);
22022 }
22023 else
22024 {
22025
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if(!skippedaframe && (tmpscr[t].tilewarptype[index]!=wtNOWARP))
22026 {
22027 FFCore.warpScriptCheck();
22028 draw_screen(tmpscr);
22029 advanceframe(true);
22030 }
22031
22032 1 sdir = dir;
22033 1 dowarp(0,index, warpsfx2);
22034 }
22035 1888 }
22036
22037 int32_t selectWlevel(int32_t d)
22038 {
22039 if(TriforceCount()==0)
22040 return 0;
22041
22042 word l = game->get_wlevel();
22043
22044 do
22045 {
22046 if(d==0 && (game->lvlitems[l+1] & liTRIFORCE))
22047 break;
22048 else if(d<0)
22049 l = (l==0) ? 7 : l-1;
22050 else
22051 l = (l==7) ? 0 : l+1;
22052 }
22053 while(!(game->lvlitems[l+1] & liTRIFORCE));
22054
22055 game->set_wlevel(l);
22056 return l;
22057 }
22058
22059 // Would someone tell the Dodongos to shut their yaps?!
22060 3 void kill_enemy_sfx()
22061 {
22062
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for(int32_t i=0; i<guys.Count(); i++)
22063 {
22064 if(((enemy*)guys.spr(i))->bgsfx)
22065 stop_sfx(((enemy*)guys.spr(i))->bgsfx);
22066 }
22067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (Hero.action!=inwind) stop_sfx(WAV_ZN1WHIRLWIND);
22068
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(tmpscr->room==rGANON)
22069 stop_sfx(WAV_ROAR);
22070 3 }
22071
22072 bool HeroClass::HasHeavyBoots()
22073 {
22074 for ( int32_t q = 0; q < MAXITEMS; ++q )
22075 {
22076 if ( game->item[q] && ( itemsbuf[q].family == itype_boots ) && /*iron*/ (itemsbuf[q].flags&ITEM_FLAG2) ) return true;
22077 }
22078 return false;
22079 }
22080
22081 const char *roomtype_string[rMAX] =
22082 {
22083 "(None)","Special Item","Pay for Info","Secret Money","Gamble",
22084 "Door Repair","Red Potion or Heart Container","Feed the Goriya","Triforce Check",
22085 "Potion Shop","Shop","More Bombs","Leave Money or Life","10 Rupees",
22086 "3-Stair Warp","Ganon","Zelda", "-<item pond>", "1/2 Magic Upgrade", "Learn Slash", "More Arrows","Take One Item"
22087 };
22088
22089 1 bool HeroClass::dowarp(int32_t type, int32_t index, int32_t warpsfx)
22090 {
22091 1 byte reposition_sword_postwarp = 0;
22092
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(index<0)
22093 {
22094 return false;
22095 }
22096 1 is_warping = true;
22097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 for ( int32_t q = 0; q < Lwpns.Count(); ++q )
22098 {
22099 weapon *swd=NULL;
22100 swd = (weapon*)Lwpns.spr(q);
22101 if(swd->id == (attack==wSword ? wSword : wWand))
22102 {
22103 Lwpns.del(q);
22104 }
22105 }
22106
22107 1 attackclk = charging = spins = tapping = 0;
22108 1 attack = none;
22109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ( warp_sound > 0 ) warpsfx = warp_sound;
22110 1 warp_sound = 0;
22111 1 word wdmap=0;
22112 1 byte wscr=0,wtype=0,t=0;
22113 1 bool overlay=false;
22114 1 t=(currscr<128)?0:1;
22115 1 int32_t wrindex = 0;
22116 1 bool wasSideview = isSideViewGravity(t); // (tmpscr[t].flags7 & fSIDEVIEW)!=0 && !ignoreSideview;
22117
22118 // Drawing commands probably shouldn't carry over...
22119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ( !get_bit(quest_rules,qr_SCRIPTDRAWSINWARPS) )
22120 1 script_drawing_commands.Clear();
22121
22122
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 switch(type)
22123 {
22124 case 0: // tile warp
22125 1 wtype = tmpscr[t].tilewarptype[index];
22126 1 wdmap = tmpscr[t].tilewarpdmap[index];
22127 1 wscr = tmpscr[t].tilewarpscr[index];
22128 1 overlay = get_bit(&tmpscr[t].tilewarpoverlayflags,index)?1:0;
22129 1 wrindex=(tmpscr->warpreturnc>>(index*2))&3;
22130 1 break;
22131
22132 case 1: // side warp
22133 wtype = tmpscr[t].sidewarptype[index];
22134 wdmap = tmpscr[t].sidewarpdmap[index];
22135 wscr = tmpscr[t].sidewarpscr[index];
22136 overlay = get_bit(&tmpscr[t].sidewarpoverlayflags,index)?1:0;
22137 wrindex=(tmpscr->warpreturnc>>(8+(index*2)))&3;
22138 //tmpscr->doscript = 0; //kill the currebt screen's script so that it does not continue to run during the scroll.
22139 //there is no doscript for screen scripts. They run like ffcs.
22140
22141 break;
22142
22143 case 2: // whistle warp
22144 {
22145 wtype = wtWHISTLE;
22146 int32_t wind = whistleitem>-1 ? itemsbuf[whistleitem].misc2 : 8;
22147 int32_t level=0;
22148
22149 if(blowcnt==0)
22150 level = selectWlevel(0);
22151 else
22152 {
22153 for(int32_t i=0; i<abs(blowcnt); i++)
22154 level = selectWlevel(blowcnt);
22155 }
22156
22157 if(level > QMisc.warp[wind].size && QMisc.warp[wind].size>0)
22158 {
22159 level %= QMisc.warp[wind].size;
22160 game->set_wlevel(level);
22161 }
22162
22163 wdmap = QMisc.warp[wind].dmap[level];
22164 wscr = QMisc.warp[wind].scr[level];
22165 }
22166 break;
22167
22168 case 3:
22169 wtype = wtIWARP;
22170 wdmap = cheat_goto_dmap;
22171 wscr = cheat_goto_screen;
22172 break;
22173
22174 case 4:
22175 wtype = wtIWARP;
22176 wdmap = currdmap;
22177 wscr = homescr-DMaps[currdmap].xoff;
22178 break;
22179 }
22180
22181 1 bool intradmap = (wdmap == currdmap);
22182 1 int32_t olddmap = currdmap;
22183 1 rehydratelake(type!=wtSCROLL);
22184
22185
1/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1 switch(wtype)
22186 {
22187 case wtCAVE:
22188 {
22189 // cave/item room
22190 1 ALLOFF();
22191 1 homescr=currscr;
22192 1 currscr=0x80;
22193
22194
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(DMaps[currdmap].flags&dmfCAVES) // cave
22195 {
22196 1 music_stop();
22197 1 kill_sfx();
22198
22199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(tmpscr->room==rWARP)
22200 {
22201 currscr=0x81;
22202 specialcave = STAIRCAVE;
22203 }
22204 1 else specialcave = GUYCAVE;
22205
22206 //lighting(2,dir);
22207 1 lighting(false, true);
22208 1 loadlvlpal(10);
22209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 bool b2 = COOLSCROLL&&
22210 ((combobuf[MAPCOMBO(x,y-16)].type==cCAVE)||(combobuf[MAPCOMBO(x,y-16)].type==cCAVE2)||
22211 (combobuf[MAPCOMBO(x,y-16)].type==cCAVEB)||(combobuf[MAPCOMBO(x,y-16)].type==cCAVE2B)||
22212 (combobuf[MAPCOMBO(x,y-16)].type==cCAVEC)||(combobuf[MAPCOMBO(x,y-16)].type==cCAVE2C)||
22213 (combobuf[MAPCOMBO(x,y-16)].type==cCAVED)||(combobuf[MAPCOMBO(x,y-16)].type==cCAVE2D));
22214 1 blackscr(30,b2?false:true);
22215 1 loadscr(0,wdmap,currscr,up,false);
22216 1 loadscr(1,wdmap,homescr,up,false);
22217 //preloaded freeform combos
22218 1 ffscript_engine(true);
22219 1 putscr(scrollbuf,0,0,tmpscr);
22220 1 putscrdoors(scrollbuf,0,0,tmpscr);
22221 1 dir=up;
22222 1 x=112;
22223 1 y=160;
22224
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(didpit)
22225 {
22226 didpit=false;
22227 x=pitx;
22228 y=pity;
22229 }
22230
22231 1 reset_hookshot();
22232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(reposition_sword_postwarp)
22233 {
22234 weapon *swd=NULL;
22235 for(int32_t i=0; i<Lwpns.Count(); i++)
22236 {
22237 swd = (weapon*)Lwpns.spr(i);
22238
22239 if(swd->id == (attack==wSword ? wSword : wWand))
22240 {
22241 int32_t itype = (attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : itype_sword);
22242 int32_t item_id = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype);
22243 positionSword(swd,item_id);
22244 break;
22245 }
22246 }
22247 }
22248 1 stepforward(diagonalMovement?5:6, false);
22249 1 }
22250 else // item room
22251 {
22252 specialcave = ITEMCELLAR;
22253 map_bkgsfx(false);
22254 kill_enemy_sfx();
22255 draw_screen(tmpscr,false);
22256
22257 //unless the room is already dark, fade to black
22258 if(!darkroom)
22259 {
22260 darkroom = true;
22261 fade(DMaps[currdmap].color,true,false);
22262 }
22263
22264 blackscr(30,true);
22265 loadscr(0,wdmap,currscr,down,false);
22266 loadscr(1,wdmap,homescr,-1,false);
22267 if ( dontdraw < 2 ) { dontdraw=1; }
22268 draw_screen(tmpscr);
22269 fade(11,true,true);
22270 darkroom = false;
22271 dir=down;
22272 x=48;
22273 y=0;
22274
22275 // is this didpit check necessary?
22276 if(didpit)
22277 {
22278 didpit=false;
22279 x=pitx;
22280 y=pity;
22281 }
22282
22283 reset_hookshot();
22284 if(reposition_sword_postwarp)
22285 {
22286 weapon *swd=NULL;
22287 for(int32_t i=0; i<Lwpns.Count(); i++)
22288 {
22289 swd = (weapon*)Lwpns.spr(i);
22290
22291 if(swd->id == (attack==wSword ? wSword : wWand))
22292 {
22293 int32_t itype = (attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : itype_sword);
22294 int32_t item_id = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype);
22295 positionSword(swd,item_id);
22296 break;
22297 }
22298 }
22299 }
22300 lighting(false, true);
22301 if ( dontdraw < 2 ) { dontdraw=0; }
22302 stepforward(diagonalMovement?16:18, false);
22303 }
22304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (get_bit(quest_rules,qr_SCREEN80_OWN_MUSIC)) playLevelMusic();
22305 1 break;
22306 }
22307
22308 case wtPASS: // passageway
22309 {
22310 map_bkgsfx(false);
22311 kill_enemy_sfx();
22312 ALLOFF();
22313 //play sound
22314 if(warpsfx > 0) sfx(warpsfx,pan(x.getInt()));
22315 homescr=currscr;
22316 currscr=0x81;
22317 specialcave = PASSAGEWAY;
22318 byte warpscr2 = wscr + DMaps[wdmap].xoff;
22319 draw_screen(tmpscr,false);
22320
22321 if(!get_bit(quest_rules, qr_NEW_DARKROOM))
22322 {
22323 if(!darkroom)
22324 fade(DMaps[currdmap].color,true,false);
22325
22326 darkroom=true;
22327 }
22328 blackscr(30,true);
22329 loadscr(0,wdmap,currscr,down,false);
22330 loadscr(1,wdmap,homescr,-1,false);
22331 //preloaded freeform combos
22332 ffscript_engine(true);
22333 if ( dontdraw < 2 ) { dontdraw=1; }
22334 draw_screen(tmpscr);
22335 lighting(false, true);
22336 dir=down;
22337 x=48;
22338
22339 if((homescr&15) > (warpscr2&15))
22340 {
22341 x=192;
22342 }
22343
22344 if((homescr&15) == (warpscr2&15))
22345 {
22346 if((currscr>>4) > (warpscr2>>4))
22347 {
22348 x=192;
22349 }
22350 }
22351
22352 // is this didpit check necessary?
22353 if(didpit)
22354 {
22355 didpit=false;
22356 x=pitx;
22357 y=pity;
22358 }
22359
22360 y=0;
22361 set_respawn_point();
22362 trySideviewLadder();
22363 reset_hookshot();
22364 if(reposition_sword_postwarp)
22365 {
22366 weapon *swd=NULL;
22367 for(int32_t i=0; i<Lwpns.Count(); i++)
22368 {
22369 swd = (weapon*)Lwpns.spr(i);
22370
22371 if(swd->id == (attack==wSword ? wSword : wWand))
22372 {
22373 int32_t itype = (attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : itype_sword);
22374 int32_t item_id = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype);
22375 positionSword(swd,item_id);
22376 break;
22377 }
22378 }
22379 }
22380 if ( dontdraw < 2 ) { dontdraw=0; }
22381 stepforward(diagonalMovement?16:18, false);
22382 newscr_clk=frame;
22383 activated_timed_warp=false;
22384 stepoutindex=index;
22385 stepoutscr = warpscr2;
22386 stepoutdmap = wdmap;
22387 stepoutwr=wrindex;
22388 }
22389 break;
22390
22391 case wtEXIT: // entrance/exit
22392 {
22393 lighting(false,false,pal_litRESETONLY);//Reset permLit, and do nothing else; lighting was not otherwise called on a wtEXIT warp.
22394 ALLOFF();
22395 music_stop();
22396 kill_sfx();
22397 blackscr(30,false);
22398 bool changedlevel = false;
22399 bool changeddmap = false;
22400 if(currdmap != wdmap)
22401 {
22402 timeExitAllGenscript(GENSCR_ST_CHANGE_DMAP);
22403 changeddmap = true;
22404 }
22405 if(dlevel != DMaps[wdmap].level)
22406 {
22407 timeExitAllGenscript(GENSCR_ST_CHANGE_LEVEL);
22408 changedlevel = true;
22409 }
22410 dlevel = DMaps[wdmap].level;
22411 currdmap = wdmap;
22412 if(changeddmap)
22413 {
22414 throwGenScriptEvent(GENSCR_EVENT_CHANGE_DMAP);
22415 }
22416 if(changedlevel)
22417 {
22418 throwGenScriptEvent(GENSCR_EVENT_CHANGE_LEVEL);
22419 }
22420
22421 currmap=DMaps[currdmap].map;
22422 init_dmap();
22423 update_subscreens(wdmap);
22424 loadfullpal();
22425 ringcolor(false);
22426 loadlvlpal(DMaps[currdmap].color);
22427 //lastentrance_dmap = currdmap;
22428 homescr = currscr = wscr + DMaps[currdmap].xoff;
22429 loadscr(0,currdmap,currscr,-1,overlay);
22430
22431 if((tmpscr->flags&fDARK) && !get_bit(quest_rules,qr_NEW_DARKROOM))
22432 {
22433 if(get_bit(quest_rules,qr_FADE))
22434 {
22435 interpolatedfade();
22436 }
22437 else
22438 {
22439 loadfadepal((DMaps[currdmap].color)*pdLEVEL+poFADE3);
22440 }
22441
22442 darkroom=naturaldark=true;
22443 }
22444 else
22445 {
22446 darkroom=naturaldark=false;
22447 }
22448
22449 int32_t wrx,wry;
22450
22451 if(get_bit(quest_rules,qr_NOARRIVALPOINT))
22452 {
22453 wrx=tmpscr->warpreturnx[0];
22454 wry=tmpscr->warpreturny[0];
22455 }
22456 else
22457 {
22458 wrx=tmpscr->warparrivalx;
22459 wry=tmpscr->warparrivaly;
22460 }
22461
22462 if(((wrx>0||wry>0)||(get_bit(quest_rules,qr_WARPSIGNOREARRIVALPOINT)))&&(!(tmpscr->flags6&fNOCONTINUEHERE)))
22463 {
22464 if(dlevel)
22465 {
22466 lastentrance = currscr;
22467 }
22468 else
22469 {
22470 lastentrance = DMaps[currdmap].cont + DMaps[currdmap].xoff;
22471 }
22472
22473 lastentrance_dmap = wdmap;
22474 }
22475
22476 if(dlevel)
22477 {
22478 if(get_bit(quest_rules,qr_NOARRIVALPOINT))
22479 {
22480 x=tmpscr->warpreturnx[wrindex];
22481 y=tmpscr->warpreturny[wrindex];
22482 }
22483 else
22484 {
22485 x=tmpscr->warparrivalx;
22486 y=tmpscr->warparrivaly;
22487 }
22488 }
22489 else
22490 {
22491 x=tmpscr->warpreturnx[wrindex];
22492 y=tmpscr->warpreturny[wrindex];
22493 }
22494
22495 if(didpit)
22496 {
22497 didpit=false;
22498 x=pitx;
22499 y=pity;
22500 }
22501
22502 dir=down;
22503
22504 if(x==0) dir=right;
22505
22506 if(x==240) dir=left;
22507
22508 if(y==0) dir=down;
22509
22510 if(y==160) dir=up;
22511
22512 if(dlevel)
22513 {
22514 // reset enemy kill counts
22515 for(int32_t i=0; i<128; i++)
22516 {
22517 game->guys[(currmap*MAPSCRSNORMAL)+i] = 0;
22518 game->maps[(currmap*MAPSCRSNORMAL)+i] &= ~mTMPNORET;
22519 }
22520 }
22521
22522 markBmap(dir^1);
22523 //preloaded freeform combos
22524 ffscript_engine(true);
22525
22526 reset_hookshot();
22527 if(reposition_sword_postwarp)
22528 {
22529 weapon *swd=NULL;
22530 for(int32_t i=0; i<Lwpns.Count(); i++)
22531 {
22532 swd = (weapon*)Lwpns.spr(i);
22533
22534 if(swd->id == (attack==wSword ? wSword : wWand))
22535 {
22536 int32_t itype = (attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : itype_sword);
22537 int32_t item_id = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype);
22538 positionSword(swd,item_id);
22539 break;
22540 }
22541 }
22542 }
22543
22544 if(isdungeon())
22545 {
22546 openscreen();
22547 if(get_bit(extra_rules, er_SHORTDGNWALK)==0 && get_bit(quest_rules, qr_SHORTDGNWALK)==0)
22548 stepforward(diagonalMovement?11:12, false);
22549 else
22550 // Didn't walk as far pre-1.93, and some quests depend on that
22551 stepforward(8, false);
22552 }
22553 else
22554 {
22555 if(!COOLSCROLL)
22556 openscreen();
22557
22558 int32_t type1 = combobuf[MAPCOMBO(x,y-16)].type; // Old-style blue square placement
22559 int32_t type2 = combobuf[MAPCOMBO(x,y)].type;
22560 int32_t type3 = combobuf[MAPCOMBO(x,y+16)].type; // More old-style blue square placement
22561
22562 if((type1==cCAVE)||(type1>=cCAVEB && type1<=cCAVED) || (type2==cCAVE)||(type2>=cCAVEB && type2<=cCAVED))
22563 {
22564 reset_pal_cycling();
22565 putscr(scrollbuf,0,0,tmpscr);
22566 putscrdoors(scrollbuf,0,0,tmpscr);
22567 walkup(COOLSCROLL);
22568 }
22569 else if((type3==cCAVE2)||(type3>=cCAVE2B && type3<=cCAVE2D) || (type2==cCAVE2)||(type2>=cCAVE2B && type2<=cCAVE2D))
22570 {
22571 reset_pal_cycling();
22572 putscr(scrollbuf,0,0,tmpscr);
22573 putscrdoors(scrollbuf,0,0,tmpscr);
22574 walkdown2(COOLSCROLL);
22575 }
22576 else if(COOLSCROLL)
22577 {
22578 openscreen();
22579 }
22580 }
22581
22582 show_subscreen_life=true;
22583 show_subscreen_numbers=true;
22584 playLevelMusic();
22585 currcset=DMaps[currdmap].color;
22586 dointro();
22587 set_respawn_point();
22588 trySideviewLadder();
22589
22590 for(int32_t i=0; i<6; i++)
22591 visited[i]=-1;
22592
22593 break;
22594 }
22595
22596 case wtSCROLL: // scrolling warp
22597 {
22598 int32_t c = DMaps[currdmap].color;
22599 scrolling_map = currmap;
22600 currmap = DMaps[wdmap].map;
22601 update_subscreens(wdmap);
22602
22603 dlevel = DMaps[wdmap].level;
22604 //check if Hero has the map for the new location before updating the subscreen. ? -Z
22605 //This works only in one direction, if Hero had a map, to not having one.
22606 //If Hero does not have a map, and warps somewhere where he does, then the map still briefly shows.
22607 update_subscreens(wdmap);
22608
22609 /*if ( has_item(itype_map, dlevel) )
22610 {
22611 //Blank the map during an intra-dmap scrolling warp.
22612 dlevel = -1; //a hack for the minimap. This works!! -Z
22613 }*/
22614
22615 // fix the scrolling direction, if it was a tile or instant warp
22616 if(type==0 || type>=3)
22617 {
22618 sdir = dir;
22619 }
22620
22621 scrollscr(sdir, wscr+DMaps[wdmap].xoff, wdmap);
22622 //dlevel = DMaps[wdmap].level; //Fix dlevel and draw the map (end hack). -Z
22623
22624 reset_hookshot();
22625 if(reposition_sword_postwarp)
22626 {
22627 weapon *swd=NULL;
22628 for(int32_t i=0; i<Lwpns.Count(); i++)
22629 {
22630 swd = (weapon*)Lwpns.spr(i);
22631
22632 if(swd->id == (attack==wSword ? wSword : wWand))
22633 {
22634 int32_t itype = (attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : itype_sword);
22635 int32_t item_id = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype);
22636 positionSword(swd,item_id);
22637 break;
22638 }
22639 }
22640 }
22641 if(!intradmap)
22642 {
22643 homescr = currscr = wscr + DMaps[wdmap].xoff;
22644 init_dmap();
22645
22646 int32_t wrx,wry;
22647
22648 if(get_bit(quest_rules,qr_NOARRIVALPOINT))
22649 {
22650 wrx=tmpscr->warpreturnx[0];
22651 wry=tmpscr->warpreturny[0];
22652 }
22653 else
22654 {
22655 wrx=tmpscr->warparrivalx;
22656 wry=tmpscr->warparrivaly;
22657 }
22658
22659 if(((wrx>0||wry>0)||(get_bit(quest_rules,qr_WARPSIGNOREARRIVALPOINT)))&&(!get_bit(quest_rules,qr_NOSCROLLCONTINUE))&&(!(tmpscr->flags6&fNOCONTINUEHERE)))
22660 {
22661 if(dlevel)
22662 {
22663 lastentrance = currscr;
22664 }
22665 else
22666 {
22667 lastentrance = DMaps[currdmap].cont + DMaps[currdmap].xoff;
22668 }
22669
22670 lastentrance_dmap = wdmap;
22671 }
22672 }
22673 if(DMaps[currdmap].color != c)
22674 {
22675 lighting(false, true);
22676 }
22677
22678 playLevelMusic();
22679 currcset=DMaps[currdmap].color;
22680 dointro();
22681 }
22682 break;
22683
22684 case wtWHISTLE: // whistle warp
22685 {
22686 scrolling_map = currmap;
22687 currmap = DMaps[wdmap].map;
22688 scrollscr(index, wscr+DMaps[wdmap].xoff, wdmap);
22689 reset_hookshot();
22690 currdmap=wdmap;
22691 dlevel=DMaps[currdmap].level;
22692 lighting(false, true);
22693 init_dmap();
22694
22695 playLevelMusic();
22696 currcset=DMaps[currdmap].color;
22697 dointro();
22698 action=inwind; FFCore.setHeroAction(inwind);
22699 int32_t wry;
22700
22701 if(get_bit(quest_rules,qr_NOARRIVALPOINT))
22702 wry=tmpscr->warpreturny[0];
22703 else wry=tmpscr->warparrivaly;
22704
22705 int32_t wrx;
22706
22707 if(get_bit(quest_rules,qr_NOARRIVALPOINT))
22708 wrx=tmpscr->warpreturnx[0];
22709 else wrx=tmpscr->warparrivalx;
22710
22711 Lwpns.add(new weapon((zfix)(index==left?240:index==right?0:wrx),(zfix)(index==down?0:index==up?160:wry),
22712 (zfix)0,wWind,1,0,index,whistleitem,getUID(),false,false,true,1));
22713 whirlwind=255;
22714 whistleitem=-1;
22715 }
22716 break;
22717
22718 case wtIWARP:
22719 case wtIWARPBLK:
22720 case wtIWARPOPEN:
22721 case wtIWARPZAP:
22722 case wtIWARPWAVE: // insta-warps
22723 {
22724 bool old_192 = false;
22725 if (get_bit(quest_rules,qr_192b163_WARP))
22726 {
22727 if ( wtype == wtIWARPWAVE )
22728 {
22729 wtype = wtIWARPWAVE;
22730 old_192 = true;
22731 }
22732 if ( old_192 )
22733 {
22734 al_trace("Encountered a warp in a 1.92b163 style quest, that was set as a Wave Warp.\n %s\n", "Trying to redirect it into a Cancel Effect");
22735 didpit=false;
22736 update_subscreens();
22737 warp_sound = 0;
22738 is_warping = false;
22739 return false;
22740 }
22741 }
22742 //for determining whether to exit cave
22743 int32_t type1 = combobuf[MAPCOMBO(x,y-16)].type;
22744 int32_t type2 = combobuf[MAPCOMBO(x,y)].type;
22745 int32_t type3 = combobuf[MAPCOMBO(x,y+16)].type;
22746
22747 bool cavewarp = ((type1==cCAVE)||(type1>=cCAVEB && type1<=cCAVED) || (type2==cCAVE)||(type2>=cCAVEB && type2<=cCAVED)
22748 ||(type3==cCAVE2)||(type3>=cCAVE2B && type3<=cCAVE2D) || (type2==cCAVE2)||(type2>=cCAVE2B && type2<=cCAVE2D));
22749
22750 if(!(tmpscr->flags3&fIWARPFULLSCREEN))
22751 {
22752 //ALLOFF kills the action, but we want to preserve Hero's action if he's swimming or diving -DD
22753 bool wasswimming = (action == swimming);
22754 int32_t olddiveclk = diveclk;
22755 ALLOFF();
22756
22757 if(wasswimming)
22758 {
22759 Hero.SetSwim();
22760 diveclk = olddiveclk;
22761 }
22762
22763 kill_sfx();
22764 }
22765 //play sound
22766 if(warpsfx > 0) sfx(warpsfx,pan(x.getInt()));
22767 if(wtype==wtIWARPZAP)
22768 {
22769 zapout();
22770 }
22771 else if(wtype==wtIWARPWAVE)
22772 {
22773 //only draw Hero if he's not in a cave -DD
22774 wavyout(!cavewarp);
22775 }
22776 else if(wtype!=wtIWARP)
22777 {
22778 bool b2 = COOLSCROLL&&cavewarp;
22779 blackscr(30,b2?false:true);
22780 }
22781
22782 int32_t c = DMaps[currdmap].color;
22783 bool changedlevel = false;
22784 bool changeddmap = false;
22785 if(currdmap != wdmap)
22786 {
22787 timeExitAllGenscript(GENSCR_ST_CHANGE_DMAP);
22788 changeddmap = true;
22789 }
22790 if(dlevel != DMaps[wdmap].level)
22791 {
22792 timeExitAllGenscript(GENSCR_ST_CHANGE_LEVEL);
22793 changedlevel = true;
22794 }
22795 dlevel = DMaps[wdmap].level;
22796 currdmap = wdmap;
22797 if(changeddmap)
22798 {
22799 throwGenScriptEvent(GENSCR_EVENT_CHANGE_DMAP);
22800 }
22801 if(changedlevel)
22802 {
22803 throwGenScriptEvent(GENSCR_EVENT_CHANGE_LEVEL);
22804 }
22805
22806 currmap = DMaps[currdmap].map;
22807 init_dmap();
22808 update_subscreens(wdmap);
22809
22810 ringcolor(false);
22811
22812 if(DMaps[currdmap].color != c)
22813 loadlvlpal(DMaps[currdmap].color);
22814
22815 homescr = currscr = wscr + DMaps[currdmap].xoff;
22816
22817 lightingInstant(); // Also sets naturaldark
22818
22819 loadscr(0,currdmap,currscr,-1,overlay);
22820
22821 x = tmpscr->warpreturnx[wrindex];
22822 y = tmpscr->warpreturny[wrindex];
22823
22824 if(didpit)
22825 {
22826 didpit=false;
22827 x=pitx;
22828 y=pity;
22829 }
22830
22831 type1 = combobuf[MAPCOMBO(x,y-16)].type;
22832 type2 = combobuf[MAPCOMBO(x,y)].type;
22833 type3 = combobuf[MAPCOMBO(x,y+16)].type;
22834
22835 if(x==0) dir=right;
22836
22837 if(x==240) dir=left;
22838
22839 if(y==0) dir=down;
22840
22841 if(y==160) dir=up;
22842
22843 markBmap(dir^1);
22844
22845 int32_t checkwater = iswaterex(MAPCOMBO(x,y+8), currmap, currscr, -1, x,y+(bigHitbox?8:12)); //iswaterex can be intensive, so let's avoid as many calls as we can.
22846
22847 if(checkwater && _walkflag(x,y+(bigHitbox?8:12),0,SWITCHBLOCK_STATE) && current_item(itype_flippers) > 0 && current_item(itype_flippers) >= combobuf[checkwater].attribytes[0] && (!(combobuf[checkwater].usrflags&cflag1) || (itemsbuf[current_item_id(itype_flippers)].flags & ITEM_FLAG3)))
22848 {
22849 hopclk=0xFF;
22850 SetSwim();
22851 if (!IsSideSwim()) attackclk = charging = spins = 0;
22852 }
22853 else
22854 {
22855 action = none; FFCore.setHeroAction(none);
22856 }
22857 //preloaded freeform combos
22858 ffscript_engine(true);
22859
22860 putscr(scrollbuf,0,0,tmpscr);
22861 putscrdoors(scrollbuf,0,0,tmpscr);
22862
22863 if((type1==cCAVE)||(type1>=cCAVEB && type1<=cCAVED) || (type2==cCAVE)||(type2>=cCAVEB && type2<=cCAVED))
22864 {
22865 reset_pal_cycling();
22866 putscr(scrollbuf,0,0,tmpscr);
22867 putscrdoors(scrollbuf,0,0,tmpscr);
22868 walkup(COOLSCROLL);
22869 }
22870 else if((type3==cCAVE2)||(type3>=cCAVE2B && type3<=cCAVE2D) || (type2==cCAVE2)||(type2>=cCAVE2B && type2<=cCAVE2D))
22871 {
22872 reset_pal_cycling();
22873 putscr(scrollbuf,0,0,tmpscr);
22874 putscrdoors(scrollbuf,0,0,tmpscr);
22875 walkdown2(COOLSCROLL);
22876 }
22877 else if(wtype==wtIWARPZAP)
22878 {
22879 zapin();
22880 }
22881 else if(wtype==wtIWARPWAVE)
22882 {
22883 wavyin();
22884 }
22885 else if(wtype==wtIWARPOPEN)
22886 {
22887 openscreen();
22888 }
22889 if(reposition_sword_postwarp)
22890 {
22891 weapon *swd=NULL;
22892 for(int32_t i=0; i<Lwpns.Count(); i++)
22893 {
22894 swd = (weapon*)Lwpns.spr(i);
22895
22896 if(swd->id == (attack==wSword ? wSword : wWand))
22897 {
22898 int32_t itype = (attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : itype_sword);
22899 int32_t item_id = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype);
22900 positionSword(swd,item_id);
22901 break;
22902 }
22903 }
22904 }
22905 show_subscreen_life=true;
22906 show_subscreen_numbers=true;
22907 playLevelMusic();
22908 currcset=DMaps[currdmap].color;
22909 dointro();
22910 set_respawn_point();
22911 trySideviewLadder();
22912 }
22913 break;
22914
22915
22916 case wtNOWARP:
22917 {
22918 bool old_192 = false;
22919 if (get_bit(quest_rules,qr_192b163_WARP))
22920 {
22921 wtype = wtIWARPWAVE;
22922 old_192 = true;
22923 }
22924 if ( old_192 )
22925 {
22926 al_trace("Encountered a warp in a 1.92b163 style quest, that was set as a Cancel Warp.\n %s\n", "Trying to redirect it into a Wave Effect");
22927 //for determining whether to exit cave
22928 int32_t type1 = combobuf[MAPCOMBO(x,y-16)].type;
22929 int32_t type2 = combobuf[MAPCOMBO(x,y)].type;
22930 int32_t type3 = combobuf[MAPCOMBO(x,y+16)].type;
22931
22932 bool cavewarp = ((type1==cCAVE)||(type1>=cCAVEB && type1<=cCAVED) || (type2==cCAVE)||(type2>=cCAVEB && type2<=cCAVED)
22933 ||(type3==cCAVE2)||(type3>=cCAVE2B && type3<=cCAVE2D) || (type2==cCAVE2)||(type2>=cCAVE2B && type2<=cCAVE2D));
22934
22935 if(!(tmpscr->flags3&fIWARPFULLSCREEN))
22936 {
22937 //ALLOFF kills the action, but we want to preserve Hero's action if he's swimming or diving -DD
22938 bool wasswimming = (action == swimming);
22939 int32_t olddiveclk = diveclk;
22940 ALLOFF();
22941
22942 if(wasswimming)
22943 {
22944 Hero.SetSwim();
22945 diveclk = olddiveclk;
22946 }
22947
22948 kill_sfx();
22949 }
22950 //play sound
22951 if(warpsfx > 0) sfx(warpsfx,pan(x.getInt()));
22952 if(wtype==wtIWARPZAP)
22953 {
22954 zapout();
22955 }
22956 else if(wtype==wtIWARPWAVE)
22957 {
22958 //only draw Hero if he's not in a cave -DD
22959 wavyout(!cavewarp);
22960 }
22961 else if(wtype!=wtIWARP)
22962 {
22963 bool b2 = COOLSCROLL&&cavewarp;
22964 blackscr(30,b2?false:true);
22965 }
22966
22967 int32_t c = DMaps[currdmap].color;
22968 bool changedlevel = false;
22969 bool changeddmap = false;
22970 if(currdmap != wdmap)
22971 {
22972 timeExitAllGenscript(GENSCR_ST_CHANGE_DMAP);
22973 changeddmap = true;
22974 }
22975 if(dlevel != DMaps[wdmap].level)
22976 {
22977 timeExitAllGenscript(GENSCR_ST_CHANGE_LEVEL);
22978 changedlevel = true;
22979 }
22980 dlevel = DMaps[wdmap].level;
22981 currdmap = wdmap;
22982 if(changeddmap)
22983 {
22984 throwGenScriptEvent(GENSCR_EVENT_CHANGE_DMAP);
22985 }
22986 if(changedlevel)
22987 {
22988 throwGenScriptEvent(GENSCR_EVENT_CHANGE_LEVEL);
22989 }
22990 currmap = DMaps[currdmap].map;
22991 init_dmap();
22992 update_subscreens(wdmap);
22993
22994 ringcolor(false);
22995
22996 if(DMaps[currdmap].color != c)
22997 loadlvlpal(DMaps[currdmap].color);
22998
22999 homescr = currscr = wscr + DMaps[currdmap].xoff;
23000
23001 lightingInstant(); // Also sets naturaldark
23002
23003 loadscr(0,currdmap,currscr,-1,overlay);
23004
23005 x = tmpscr->warpreturnx[wrindex];
23006 y = tmpscr->warpreturny[wrindex];
23007
23008 if(didpit)
23009 {
23010 didpit=false;
23011 x=pitx;
23012 y=pity;
23013 }
23014
23015 type1 = combobuf[MAPCOMBO(x,y-16)].type;
23016 type2 = combobuf[MAPCOMBO(x,y)].type;
23017 type3 = combobuf[MAPCOMBO(x,y+16)].type;
23018
23019 if(x==0) dir=right;
23020
23021 if(x==240) dir=left;
23022
23023 if(y==0) dir=down;
23024
23025 if(y==160) dir=up;
23026
23027 markBmap(dir^1);
23028
23029 if(iswaterex(MAPCOMBO(x,y+8), currmap, currscr, -1, x,y+8) && _walkflag(x,y+8,0,SWITCHBLOCK_STATE) && current_item(itype_flippers))
23030 {
23031 hopclk=0xFF;
23032 SetSwim();
23033 if (!IsSideSwim()) attackclk = charging = spins = 0;
23034 }
23035 else
23036 {
23037 action = none;
23038 FFCore.setHeroAction(none);
23039 }
23040 //preloaded freeform combos
23041 ffscript_engine(true);
23042
23043 putscr(scrollbuf,0,0,tmpscr);
23044 putscrdoors(scrollbuf,0,0,tmpscr);
23045
23046 if((type1==cCAVE)||(type1>=cCAVEB && type1<=cCAVED) || (type2==cCAVE)||(type2>=cCAVEB && type2<=cCAVED))
23047 {
23048 reset_pal_cycling();
23049 putscr(scrollbuf,0,0,tmpscr);
23050 putscrdoors(scrollbuf,0,0,tmpscr);
23051 walkup(COOLSCROLL);
23052 }
23053 else if((type3==cCAVE2)||(type3>=cCAVE2B && type3<=cCAVE2D) || (type2==cCAVE2)||(type2>=cCAVE2B && type2<=cCAVE2D))
23054 {
23055 reset_pal_cycling();
23056 putscr(scrollbuf,0,0,tmpscr);
23057 putscrdoors(scrollbuf,0,0,tmpscr);
23058 walkdown2(COOLSCROLL);
23059 }
23060 else if(wtype==wtIWARPZAP)
23061 {
23062 zapin();
23063 }
23064 else if(wtype==wtIWARPWAVE)
23065 {
23066 wavyin();
23067 }
23068 else if(wtype==wtIWARPOPEN)
23069 {
23070 openscreen();
23071 }
23072 if(reposition_sword_postwarp)
23073 {
23074 weapon *swd=NULL;
23075 for(int32_t i=0; i<Lwpns.Count(); i++)
23076 {
23077 swd = (weapon*)Lwpns.spr(i);
23078
23079 if(swd->id == (attack==wSword ? wSword : wWand))
23080 {
23081 int32_t itype = (attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : itype_sword);
23082 int32_t item_id = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype);
23083 positionSword(swd,item_id);
23084 break;
23085 }
23086 }
23087 }
23088 show_subscreen_life=true;
23089 show_subscreen_numbers=true;
23090 playLevelMusic();
23091 currcset=DMaps[currdmap].color;
23092 dointro();
23093 set_respawn_point();
23094 trySideviewLadder();
23095 break;
23096 }
23097 else
23098 {
23099 if(reposition_sword_postwarp)
23100 {
23101 weapon *swd=NULL;
23102 for(int32_t i=0; i<Lwpns.Count(); i++)
23103 {
23104 swd = (weapon*)Lwpns.spr(i);
23105
23106 if(swd->id == (attack==wSword ? wSword : wWand))
23107 {
23108 int32_t itype = (attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : itype_sword);
23109 int32_t item_id = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype);
23110 positionSword(swd,item_id);
23111 break;
23112 }
23113 }
23114 }
23115 didpit=false;
23116 update_subscreens();
23117 warp_sound = 0;
23118 is_warping = false;
23119 return false;
23120 }
23121 }
23122 default:
23123 didpit=false;
23124 update_subscreens();
23125 warp_sound = 0;
23126 is_warping = false;
23127 if(reposition_sword_postwarp)
23128 {
23129 weapon *swd=NULL;
23130 for(int32_t i=0; i<Lwpns.Count(); i++)
23131 {
23132 swd = (weapon*)Lwpns.spr(i);
23133
23134 if(swd->id == (attack==wSword ? wSword : wWand))
23135 {
23136 int32_t itype = (attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : itype_sword);
23137 int32_t item_id = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype);
23138 positionSword(swd,item_id);
23139 break;
23140 }
23141 }
23142 }
23143 return false;
23144 }
23145
23146
23147
23148 // Stop Hero from drowning!
23149
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if(action==drowning || action==lavadrowning || action==sidedrowning)
23150 {
23151 drownclk=0;
23152 drownclk=0;
23153 action=none; FFCore.setHeroAction(none);
23154 }
23155
23156 1 int32_t checkwater = iswaterex(MAPCOMBO(x,y+(bigHitbox?8:12)), currmap, currscr, -1, x,y+(bigHitbox?8:12));
23157 // But keep him swimming if he ought to be!
23158 // Unless the water is too high levelled, in which case... well, he'll drown on transition probably anyways. -Dimi
23159
3/12
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
1 if(action!=rafting && checkwater && (_walkflag(x,y+(bigHitbox?8:12),0,SWITCHBLOCK_STATE) || get_bit(quest_rules,qr_DROWN))
23160 //&& (current_item(itype_flippers) >= combobuf[checkwater].attribytes[0])
23161 && (action!=inwind))
23162 {
23163 hopclk=0xFF;
23164 SetSwim();
23165 }
23166
23167 1 newscr_clk=frame;
23168 1 activated_timed_warp=false;
23169 1 eat_buttons();
23170
23171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(wtype!=wtIWARP)
23172 1 attackclk=0;
23173
23174 1 didstuff=0;
23175 1 usecounts.clear();
23176 1 map_bkgsfx(true);
23177 1 loadside=dir^1;
23178 1 whistleclk=-1;
23179
23180
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if((z>0 || fakez>0) && isSideViewHero())
23181 {
23182 y-=z;
23183 y-=fakez;
23184 fakez=0;
23185 z=0;
23186 }
23187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if(!isSideViewHero())
23188 {
23189 1 fall=0;
23190 1 fakefall=0;
23191 1 }
23192
23193 // If warping between top-down and sideview screens,
23194 // fix enemies that are carried over by Full Screen Warp
23195 1 const bool tmpscr_is_sideview = isSideViewHero();
23196
23197
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if(!wasSideview && tmpscr_is_sideview)
23198 {
23199 for(int32_t i=0; i<guys.Count(); i++)
23200 {
23201 if(guys.spr(i)->z > 0 || guys.spr(i)->fakez > 0)
23202 {
23203 guys.spr(i)->y -= guys.spr(i)->z;
23204 guys.spr(i)->y -= guys.spr(i)->fakez;
23205 guys.spr(i)->z = 0;
23206 guys.spr(i)->fakez = 0;
23207 }
23208
23209 if(((enemy*)guys.spr(i))->family!=eeTRAP && ((enemy*)guys.spr(i))->family!=eeSPINTILE)
23210 guys.spr(i)->yofs += 2;
23211 }
23212 }
23213
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 else if(wasSideview && !tmpscr_is_sideview)
23214 {
23215 for(int32_t i=0; i<guys.Count(); i++)
23216 {
23217 if(((enemy*)guys.spr(i))->family!=eeTRAP && ((enemy*)guys.spr(i))->family!=eeSPINTILE)
23218 guys.spr(i)->yofs -= 2;
23219 }
23220 }
23221
23222
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 if((DMaps[currdmap].type&dmfCONTINUE) || (currdmap==0&&get_bit(quest_rules, qr_DMAP_0_CONTINUE_BUG)))
23223 {
23224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(dlevel)
23225 {
23226 int32_t wrx,wry;
23227
23228 if(get_bit(quest_rules,qr_NOARRIVALPOINT))
23229 {
23230 wrx=tmpscr->warpreturnx[0];
23231 wry=tmpscr->warpreturny[0];
23232 }
23233 else
23234 {
23235 wrx=tmpscr->warparrivalx;
23236 wry=tmpscr->warparrivaly;
23237 }
23238
23239 if((wtype == wtEXIT)
23240 || (((wtype == wtSCROLL) && !intradmap) && ((wrx>0 || wry>0)||(get_bit(quest_rules,qr_WARPSIGNOREARRIVALPOINT)))))
23241 {
23242 if(!(wtype==wtSCROLL)||!(get_bit(quest_rules,qr_NOSCROLLCONTINUE)))
23243 {
23244 game->set_continue_scrn(homescr);
23245 //Z_message("continue_scrn = %02X e/e\n",game->get_continue_scrn());
23246 }
23247 else if(currdmap != game->get_continue_dmap())
23248 {
23249 game->set_continue_scrn(DMaps[currdmap].cont + DMaps[currdmap].xoff);
23250 }
23251 }
23252 else
23253 {
23254 if(currdmap != game->get_continue_dmap())
23255 {
23256 game->set_continue_scrn(DMaps[currdmap].cont + DMaps[currdmap].xoff);
23257 //Z_message("continue_scrn = %02X dlevel\n",game->get_continue_scrn());
23258 }
23259 }
23260 }
23261 else
23262 {
23263 1 game->set_continue_scrn(DMaps[currdmap].cont + DMaps[currdmap].xoff);
23264 //Z_message("continue_scrn = %02X\n !dlevel\n",game->get_continue_scrn());
23265 }
23266
23267 1 game->set_continue_dmap(currdmap);
23268 1 lastentrance_dmap = currdmap;
23269 1 lastentrance = game->get_continue_scrn();
23270 //Z_message("continue_map = %d\n",game->get_continue_dmap());
23271 1 }
23272
23273
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(tmpscr->flags4&fAUTOSAVE)
23274 {
23275 save_game(true,0);
23276 }
23277
23278
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(tmpscr->flags6&fCONTINUEHERE)
23279 {
23280 lastentrance_dmap = currdmap;
23281 lastentrance = homescr;
23282 }
23283
23284 1 update_subscreens();
23285 1 verifyBothWeapons();
23286
23287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(wtype==wtCAVE)
23288 {
23289
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(DMaps[currdmap].flags&dmfGUYCAVES)
23290 2 Z_eventlog("Entered %s containing %s.\n",DMaps[currdmap].flags&dmfCAVES ? "Cave" : "Item Cellar",
23291 1 (char *)moduledata.roomtype_names[tmpscr[1].room]);
23292 else
23293 Z_eventlog("Entered %s.",DMaps[currdmap].flags&dmfCAVES ? "Cave" : "Item Cellar");
23294 1 }
23295 else Z_eventlog("Warped to DMap %d: %s, screen %d, via %s.\n", currdmap, DMaps[currdmap].name,currscr,
23296 wtype==wtPASS ? "Passageway" :
23297 wtype==wtEXIT ? "Entrance/Exit" :
23298 wtype==wtSCROLL ? "Scrolling Warp" :
23299 wtype==wtWHISTLE ? "Whistle Warp" :
23300 "Insta-Warp");
23301
23302 1 eventlog_mapflags();
23303
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(reposition_sword_postwarp)
23304 {
23305 weapon *swd=NULL;
23306 for(int32_t i=0; i<Lwpns.Count(); i++)
23307 {
23308 swd = (weapon*)Lwpns.spr(i);
23309
23310 if(swd->id == (attack==wSword ? wSword : wWand))
23311 {
23312 int32_t itype = (attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : itype_sword);
23313 int32_t item_id = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype);
23314 positionSword(swd,item_id);
23315 break;
23316 }
23317 }
23318 }
23319 1 FFCore.init_combo_doscript();
23320
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (!intradmap || get_bit(quest_rules, qr_WARPS_RESTART_DMAPSCRIPT))
23321 {
23322 1 FFScript::deallocateAllArrays(SCRIPT_DMAP, olddmap);
23323 1 FFCore.initZScriptDMapScripts();
23324 1 FFCore.initZScriptActiveSubscreenScript();
23325 1 }
23326 1 is_warping = false;
23327 1 return true;
23328 1 }
23329
23330 1 void HeroClass::exitcave()
23331 {
23332 1 stop_sfx(QMisc.miscsfx[sfxLOWHEART]);
23333 1 currscr=homescr;
23334 1 loadscr(0,currdmap,currscr,255,false); // bogus direction
23335 1 x = tmpscr->warpreturnx[0];
23336 1 y = tmpscr->warpreturny[0];
23337
23338
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(didpit)
23339 {
23340 didpit=false;
23341 x=pitx;
23342 y=pity;
23343 }
23344
23345
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(x+y == 0)
23346 x = y = 80;
23347
23348 1 int32_t type1 = combobuf[MAPCOMBO(x,y-16)].type;
23349 1 int32_t type2 = combobuf[MAPCOMBO(x,y)].type;
23350 1 int32_t type3 = combobuf[MAPCOMBO(x,y+16)].type;
23351
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 bool b = COOLSCROLL &&
23352 ((type1==cCAVE) || (type1>=cCAVEB && type1<=cCAVED) ||
23353 (type2==cCAVE) || (type2>=cCAVEB && type2<=cCAVED) ||
23354 (type3==cCAVE2) || (type3>=cCAVE2B && type3<=cCAVE2D) ||
23355 (type2==cCAVE2) || (type2>=cCAVE2B && type2<=cCAVE2D));
23356 1 ALLOFF();
23357 1 blackscr(30,b?false:true);
23358 1 ringcolor(false);
23359 1 loadlvlpal(DMaps[currdmap].color);
23360 1 lighting(false, true);
23361 1 music_stop();
23362 1 kill_sfx();
23363 1 putscr(scrollbuf,0,0,tmpscr);
23364 1 putscrdoors(scrollbuf,0,0,tmpscr);
23365
23366
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1 if((type1==cCAVE)||(type1>=cCAVEB && type1<=cCAVED) || (type2==cCAVE)||(type2>=cCAVEB && type2<=cCAVED))
23367 {
23368 1 walkup(COOLSCROLL);
23369 1 }
23370 else if((type3==cCAVE2)||(type3>=cCAVE2B && type3<=cCAVE2D) || (type2==cCAVE2)||(type2>=cCAVE2B && type2<=cCAVE2D))
23371 {
23372 walkdown2(COOLSCROLL);
23373 }
23374
23375 1 show_subscreen_life=true;
23376 1 show_subscreen_numbers=true;
23377 1 playLevelMusic();
23378 1 currcset=DMaps[currdmap].color;
23379 1 dointro();
23380 1 newscr_clk=frame;
23381 1 activated_timed_warp=false;
23382 1 dir=down;
23383 1 set_respawn_point();
23384 1 eat_buttons();
23385 1 didstuff=0;
23386 1 usecounts.clear();
23387 1 map_bkgsfx(true);
23388 1 loadside=dir^1;
23389 1 }
23390
23391
23392 1 void HeroClass::stepforward(int32_t steps, bool adjust)
23393 {
23394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ( FFCore.nostepforward ) return;
23395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ( FFCore.temp_no_stepforward ) { FFCore.temp_no_stepforward = 0; return; }
23396 1 zfix tx=x; //temp x
23397 1 zfix ty=y; //temp y
23398 1 zfix tstep(0); //temp single step distance
23399 1 zfix s(0); //calculated step distance for all steps
23400 1 z3step=2;
23401 1 int32_t sh=shiftdir;
23402 1 shiftdir=-1;
23403
23404
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 for(int32_t i=steps; i>0; --i)
23405 {
23406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if(diagonalMovement)
23407 {
23408 if(get_bit(quest_rules, qr_NEW_HERO_MOVEMENT) || IsSideSwim())
23409 {
23410 tstep = 1.5;
23411 }
23412 else
23413 {
23414 tstep=z3step;
23415 z3step=(z3step%2)+1;
23416 }
23417 }
23418 else
23419 {
23420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if(get_bit(quest_rules, qr_NEW_HERO_MOVEMENT))
23421 {
23422 tstep = 1.5;
23423 }
23424 else
23425 {
23426
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 tstep=lsteps[int32_t((dir<left)?ty:tx)&7];
23427
23428
1/5
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 switch(dir)
23429 {
23430 case up:
23431 6 ty-=tstep;
23432 6 break;
23433
23434 case down:
23435 ty+=tstep;
23436 break;
23437
23438 case left:
23439 tx-=tstep;
23440 break;
23441
23442 case right:
23443 tx+=tstep;
23444 break;
23445 }
23446 }
23447 }
23448
23449 6 s+=tstep;
23450 6 }
23451
23452 1 z3step=2;
23453
23454 1 x = x.getInt();
23455 1 y = y.getInt();
23456
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 while(s>=0)
23457 {
23458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(diagonalMovement)
23459 {
23460 if((dir<left?x.getInt()&7:y.getInt()&7)&&adjust==true)
23461 {
23462 if(get_bit(quest_rules, qr_NEW_HERO_MOVEMENT) || IsSideSwim())
23463 {
23464 walkable = false;
23465 shiftdir = -1;
23466 int32_t tdir=dir<left?(x.getInt()&8?left:right):(y.getInt()&8?down:up);
23467 switch(tdir)
23468 {
23469 case left:
23470 --x;
23471 break;
23472 case right:
23473 ++x;
23474 break;
23475 case up:
23476 --y;
23477 break;
23478 case down:
23479 ++y;
23480 break;
23481 }
23482 }
23483 else
23484 {
23485 walkable=false;
23486 shiftdir=dir<left?(x.getInt()&8?left:right):(y.getInt()&8?down:up);
23487 move(dir, 150);
23488 }
23489 }
23490 else
23491 {
23492 if(get_bit(quest_rules, qr_NEW_HERO_MOVEMENT) || IsSideSwim())
23493 {
23494 s-=1.5;
23495 }
23496 else
23497 {
23498 s-=z3step;
23499 }
23500 walkable=true;
23501 move(dir, 150);
23502 }
23503
23504 shiftdir=-1;
23505 }
23506 else
23507 {
23508
2/6
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
7 if((dir<left?x.getInt()&7:y.getInt()&7)&&adjust==true)
23509 {
23510 walkable=false;
23511 int32_t tdir=dir<left?(x.getInt()&8?left:right):(y.getInt()&8?down:up);
23512 switch(tdir)
23513 {
23514 case left:
23515 --x;
23516 break;
23517 case right:
23518 ++x;
23519 break;
23520 case up:
23521 --y;
23522 break;
23523 case down:
23524 ++y;
23525 break;
23526 }
23527 }
23528 else
23529 {
23530
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if(get_bit(quest_rules, qr_NEW_HERO_MOVEMENT) || IsSideSwim())
23531 {
23532 s-=1.5;
23533 }
23534
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 else if(dir<left)
23535 {
23536 7 s-=lsteps[y.getInt()&7];
23537 7 }
23538 else
23539 {
23540 s-=lsteps[x.getInt()&7];
23541 }
23542
23543 7 move(dir, 150);
23544 }
23545 }
23546
23547
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if(s<0)
23548 {
23549 // Not quite sure how this is actually supposed to work.
23550 // There have to be two cases for each direction or Hero
23551 // either walks too far onto the screen or may get stuck
23552 // going through walk-through walls.
23553
1/5
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 switch(dir)
23554 {
23555 case up:
23556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(y<8) // Leaving the screen
23557 y+=s;
23558 else // Entering the screen
23559 1 y-=s;
23560
23561 1 break;
23562
23563 case down:
23564 if(y>152)
23565 y-=s;
23566 else
23567 y+=s;
23568
23569 break;
23570
23571 case left:
23572 if(x<8)
23573 x+=s;
23574 else
23575 x-=s;
23576
23577 break;
23578
23579 case right:
23580 if(x>=232)
23581 x-=s;
23582 else
23583 x+=s;
23584
23585 break;
23586 }
23587 1 }
23588
23589
23590 7 draw_screen(tmpscr);
23591
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (canSideviewLadder()) setOnSideviewLadder(true);
23592 7 advanceframe(true);
23593
23594
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if(Quit)
23595 return;
23596 }
23597
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if(dir==right||dir==down)
23598 {
23599 x=int32_t(x);
23600 y=int32_t(y);
23601 }
23602 else
23603 {
23604 1 x = x.getInt();
23605 1 y = y.getInt();
23606 }
23607 1 set_respawn_point();
23608 1 draw_screen(tmpscr);
23609 1 eat_buttons();
23610 1 shiftdir=sh;
23611 1 }
23612
23613 1 void HeroClass::walkdown(bool opening) //entering cave
23614 {
23615
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(opening)
23616 {
23617 close_black_opening(x+8, y+8+playing_field_offset, false);
23618 }
23619
23620 1 hclk=0;
23621 1 stop_item_sfx(itype_brang);
23622 1 sfx(WAV_STAIRS,pan(x.getInt()));
23623 1 clk=0;
23624 // int32_t cmby=(y.getInt()&0xF0)+16;
23625 // Fix Hero's position to the grid
23626 1 y=y.getInt()&0xF0;
23627 1 action=climbcoverbottom; FFCore.setHeroAction(climbcoverbottom);
23628 1 attack=wNone;
23629 1 attackid=-1;
23630 1 reset_swordcharge();
23631 1 climb_cover_x=x.getInt()&0xF0;
23632 1 climb_cover_y=(y.getInt()&0xF0)+16;
23633
23634 1 guys.clear();
23635 1 chainlinks.clear();
23636 1 Lwpns.clear();
23637 1 Ewpns.clear();
23638 1 items.clear();
23639
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 64 times.
65 for(int32_t i=0; i<64; i++)
23640 {
23641 64 herostep();
23642
23643
2/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
64 if(zinit.heroAnimationStyle==las_zelda3 || zinit.heroAnimationStyle==las_zelda3slow)
23644 hero_count=(hero_count+1)%16;
23645
23646
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 16 times.
64 if((i&3)==3)
23647 16 ++y;
23648
23649 64 draw_screen(tmpscr);
23650 64 advanceframe(true);
23651
23652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if(Quit)
23653 break;
23654 64 }
23655
23656 1 action=none; FFCore.setHeroAction(none);
23657 1 }
23658
23659 void HeroClass::walkdown2(bool opening) //exiting cave 2
23660 {
23661 int32_t type = combobuf[MAPCOMBO(x,y)].type;
23662
23663 if((type==cCAVE2)||(type>=cCAVE2B && type<=cCAVE2D))
23664 y-=16;
23665
23666 dir=down;
23667 // Fix Hero's position to the grid
23668 y=y.getInt()&0xF0;
23669 z=fakez=fall=fakefall=0;
23670
23671 if(opening)
23672 {
23673 open_black_opening(x+8, y+8+playing_field_offset+16, false);
23674 }
23675
23676 hclk=0;
23677 stop_item_sfx(itype_brang);
23678 sfx(WAV_STAIRS,pan(x.getInt()));
23679 clk=0;
23680 // int32_t cmby=y.getInt()&0xF0;
23681 action=climbcovertop; FFCore.setHeroAction(climbcovertop);
23682 attack=wNone;
23683 attackid=-1;
23684 reset_swordcharge();
23685 climb_cover_x=x.getInt()&0xF0;
23686 climb_cover_y=y.getInt()&0xF0;
23687
23688 guys.clear();
23689 chainlinks.clear();
23690 Lwpns.clear();
23691 Ewpns.clear();
23692 items.clear();
23693
23694 for(int32_t i=0; i<64; i++)
23695 {
23696 herostep();
23697
23698 if(zinit.heroAnimationStyle==las_zelda3 || zinit.heroAnimationStyle==las_zelda3slow)
23699 hero_count=(hero_count+1)%16;
23700
23701 if((i&3)==3)
23702 ++y;
23703
23704 draw_screen(tmpscr);
23705 advanceframe(true);
23706
23707 if(Quit)
23708 break;
23709 }
23710
23711 action=none; FFCore.setHeroAction(none);
23712 }
23713
23714 1 void HeroClass::walkup(bool opening) //exiting cave
23715 {
23716 1 int32_t type = combobuf[MAPCOMBO(x,y)].type;
23717
23718
2/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if((type==cCAVE)||(type>=cCAVEB && type<=cCAVED))
23719 y+=16;
23720
23721 // Fix Hero's position to the grid
23722 1 y=y.getInt()&0xF0;
23723 1 z=fakez=fall=fakefall=0;
23724
23725
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(opening)
23726 {
23727 open_black_opening(x+8, y+8+playing_field_offset-16, false);
23728 }
23729
23730 1 hclk=0;
23731 1 stop_item_sfx(itype_brang);
23732 1 sfx(WAV_STAIRS,pan(x.getInt()));
23733 1 dir=down;
23734 1 clk=0;
23735 // int32_t cmby=y.getInt()&0xF0;
23736 1 action=climbcoverbottom; FFCore.setHeroAction(climbcoverbottom);
23737 1 attack=wNone;
23738 1 attackid=-1;
23739 1 reset_swordcharge();
23740 1 climb_cover_x=x.getInt()&0xF0;
23741 1 climb_cover_y=y.getInt()&0xF0;
23742
23743 1 guys.clear();
23744 1 chainlinks.clear();
23745 1 Lwpns.clear();
23746 1 Ewpns.clear();
23747 1 items.clear();
23748
23749
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 64 times.
65 for(int32_t i=0; i<64; i++)
23750 {
23751 64 herostep();
23752
23753
2/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
64 if(zinit.heroAnimationStyle==las_zelda3 || zinit.heroAnimationStyle==las_zelda3slow)
23754 hero_count=(hero_count+1)%16;
23755
23756
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 16 times.
64 if((i&3)==0)
23757 16 --y;
23758
23759 64 draw_screen(tmpscr);
23760 64 advanceframe(true);
23761
23762
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 if(Quit)
23763 break;
23764 64 }
23765 1 map_bkgsfx(true);
23766 1 loadside=dir^1;
23767 1 action=none; FFCore.setHeroAction(none);
23768 1 }
23769
23770 void HeroClass::walkup2(bool opening) //entering cave2
23771 {
23772 if(opening)
23773 {
23774 close_black_opening(x+8, y+8+playing_field_offset, false);
23775 }
23776
23777 hclk=0;
23778 stop_item_sfx(itype_brang);
23779 sfx(WAV_STAIRS,pan(x.getInt()));
23780 dir=up;
23781 clk=0;
23782 // int32_t cmby=y.getInt()&0xF0;
23783 action=climbcovertop; FFCore.setHeroAction(climbcovertop);
23784 attack=wNone;
23785 attackid=-1;
23786 reset_swordcharge();
23787 climb_cover_x=x.getInt()&0xF0;
23788 climb_cover_y=(y.getInt()&0xF0)-16;
23789
23790 guys.clear();
23791 chainlinks.clear();
23792 Lwpns.clear();
23793 Ewpns.clear();
23794 items.clear();
23795
23796 for(int32_t i=0; i<64; i++)
23797 {
23798 herostep();
23799
23800 if(zinit.heroAnimationStyle==las_zelda3 || zinit.heroAnimationStyle==las_zelda3slow)
23801 hero_count=(hero_count+1)%16;
23802
23803 if((i&3)==0)
23804 --y;
23805
23806 draw_screen(tmpscr);
23807 advanceframe(true);
23808
23809 if(Quit)
23810 break;
23811 }
23812 map_bkgsfx(true);
23813 loadside=dir^1;
23814 action=none; FFCore.setHeroAction(none);
23815 }
23816
23817 void HeroClass::stepout() // Step out of item cellars and passageways
23818 {
23819 int32_t sc = specialcave; // This gets erased by ALLOFF()
23820 ALLOFF();
23821 stop_sfx(QMisc.miscsfx[sfxLOWHEART]);
23822 map_bkgsfx(false);
23823 kill_enemy_sfx();
23824 draw_screen(tmpscr,false);
23825 fade(sc>=GUYCAVE?10:11,true,false);
23826 blackscr(30,true);
23827 ringcolor(false);
23828
23829 if(sc==PASSAGEWAY && abs(x-warpx)>16) // How did Hero leave the passageway?
23830 {
23831 currdmap=stepoutdmap;
23832 currmap=DMaps[currdmap].map;
23833 dlevel=DMaps[currdmap].level;
23834
23835 //we might have just left a passage, so be sure to update the CSet record -DD
23836 currcset=DMaps[currdmap].color;
23837
23838 init_dmap();
23839 homescr=stepoutscr;
23840 }
23841
23842 currscr=homescr;
23843 loadscr(0,currdmap,currscr,255,false); // bogus direction
23844 draw_screen(tmpscr,false);
23845
23846 if(get_bit(quest_rules, qr_NEW_DARKROOM) || !(tmpscr->flags&fDARK))
23847 {
23848 darkroom = naturaldark = false;
23849 fade(DMaps[currdmap].color,true,true);
23850 }
23851 else
23852 {
23853 darkroom = naturaldark = true;
23854
23855 if(get_bit(quest_rules,qr_FADE))
23856 {
23857 interpolatedfade();
23858 }
23859 else
23860 {
23861 loadfadepal((DMaps[currdmap].color)*pdLEVEL+poFADE3);
23862 }
23863 byte *si = colordata + CSET(DMaps[currdmap].color*pdLEVEL+poLEVEL)*3;
23864 si+=3*48;
23865
23866 for(int32_t i=0; i<16; i++)
23867 {
23868 RAMpal[CSET(9)+i] = _RGB(si);
23869 tempgreypal[CSET(9)+i] = _RGB(si); //preserve monochrome
23870 si+=3;
23871 }
23872 }
23873
23874 x = tmpscr->warpreturnx[stepoutwr];
23875 y = tmpscr->warpreturny[stepoutwr];
23876
23877 if(didpit)
23878 {
23879 didpit=false;
23880 x=pitx;
23881 y=pity;
23882 }
23883
23884 if(x+y == 0)
23885 x = y = 80;
23886
23887 dir=down;
23888
23889 set_respawn_point();
23890
23891 // Let's use the 'exit cave' animation if we entered this cellar via a cave combo.
23892 int32_t type = combobuf[MAPCOMBO(tmpscr->warpreturnx[stepoutwr],tmpscr->warpreturny[stepoutwr])].type;
23893
23894 if((type==cCAVE)||(type>=cCAVEB && type<=cCAVED))
23895 {
23896 walkup(false);
23897 }
23898 else if((type==cCAVE2)||(type>=cCAVE2B && type<=cCAVE2D))
23899 {
23900 walkdown2(false);
23901 }
23902
23903 newscr_clk=frame;
23904 activated_timed_warp=false;
23905 didstuff=0;
23906 usecounts.clear();
23907 eat_buttons();
23908 markBmap(-1);
23909 map_bkgsfx(true);
23910
23911 if(!get_bit(quest_rules, qr_CAVEEXITNOSTOPMUSIC))
23912 {
23913 music_stop();
23914 playLevelMusic();
23915 }
23916 else if(get_bit(quest_rules,qr_SCREEN80_OWN_MUSIC))
23917 {
23918 playLevelMusic();
23919 }
23920
23921 loadside=dir^1;
23922 }
23923
23924 4 bool HeroClass::nextcombo_wf(int32_t d2)
23925 {
23926
3/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4 if(toogam || (action!=swimming && !IsSideSwim() && action != swimhit) || hopclk==0) //!DIMITODO: ...does swimming just let you ignore smart scrolling entirely!?
23927 4 return false;
23928
23929 // assumes Hero is about to scroll screens
23930
23931 int32_t ns = nextscr(d2);
23932
23933 if(ns==0xFFFF)
23934 return false;
23935
23936 // want actual screen index, not game->maps[] index
23937 ns = (ns&127) + (ns>>7)*MAPSCRS;
23938
23939 int32_t cx = x;
23940 int32_t cy = y;
23941
23942 switch(d2)
23943 {
23944 case up:
23945 cy=160;
23946 break;
23947
23948 case down:
23949 cy=0;
23950 break;
23951
23952 case left:
23953 cx=240;
23954 break;
23955
23956 case right:
23957 cx=0;
23958 break;
23959 }
23960
23961 // check lower half of combo
23962 cy += 8;
23963
23964 // from MAPCOMBO()
23965 int32_t cmb = (cy&0xF0)+(cx>>4);
23966
23967 if(cmb>175)
23968 return true;
23969
23970 newcombo c = combobuf[TheMaps[ns].data[cmb]];
23971 bool dried = iswater_type(c.type) && DRIEDLAKE;
23972 bool swim = iswater_type(c.type) && (current_item(itype_flippers)) && !dried;
23973 int32_t b=1;
23974
23975 if(cx&8) b<<=2;
23976
23977 if(cy&8) b<<=1;
23978
23979 if((c.walk&b) && !dried && !swim)
23980 return true;
23981
23982 // next block (i.e. cnt==2)
23983 if(!(cx&8))
23984 {
23985 b<<=2;
23986 }
23987 else
23988 {
23989 c = combobuf[TheMaps[ns].data[++cmb]];
23990 dried = iswater_type(c.type) && DRIEDLAKE;
23991 swim = iswater_type(c.type) && (current_item(itype_flippers)) && !dried;
23992 b=1;
23993
23994 if(cy&8)
23995 {
23996 b<<=1;
23997 }
23998 }
23999
24000 return (c.walk&b) ? !dried && !swim : false;
24001 4 }
24002
24003 bool HeroClass::nextcombo_solid(int32_t d2)
24004 {
24005 if(toogam || currscr>=128)
24006 return false;
24007
24008 // assumes Hero is about to scroll screens
24009
24010 int32_t ns = nextscr(d2);
24011
24012 if(ns==0xFFFF)
24013 return false;
24014
24015 // want actual screen index, not game->maps[] index
24016 ns = (ns&127) + (ns>>7)*MAPSCRS;
24017 int32_t screen = (ns%MAPSCRS);
24018 int32_t map = (ns - screen) / MAPSCRS;
24019
24020 int32_t cx = x;
24021 int32_t cy = y;
24022
24023 switch(d2)
24024 {
24025 case up:
24026 cy=160;
24027 break;
24028
24029 case down:
24030 cy=0;
24031 break;
24032
24033 case left:
24034 cx=240;
24035 break;
24036
24037 case right:
24038 cx=0;
24039 break;
24040 }
24041
24042 if(d2==up) cy += 8;
24043
24044 if(d2==left||d2==right) cy+=bigHitbox?0:8;
24045
24046 int32_t initcx = cx;
24047 int32_t initcy = cy;
24048 // from MAPCOMBO()
24049
24050 for(int32_t i=0; i<=((bigHitbox&&!(d2==up||d2==down))?((initcy&7)?2:1):((initcy&7)?1:0)) && cy < 176; cy+=(cy%2)?7:8,i++)
24051 {
24052 cx = initcx;
24053 for(int32_t k=0; k<=(get_bit(quest_rules, qr_SMARTER_SMART_SCROLL)?((initcx&7)?2:1):0) && cx < 256; cx+=(cx%2)?7:8,k++)
24054 {
24055 int32_t cmb = (cy&0xF0)+(cx>>4);
24056
24057 if(cmb>175)
24058 {
24059 return true;
24060 }
24061
24062 newcombo const& c = combobuf[MAPCOMBO3(map, screen, -1,cx,cy, get_bit(quest_rules, qr_SMARTER_SMART_SCROLL))];
24063
24064 int32_t b=1;
24065
24066 if(cx&8) b<<=2;
24067
24068 if(cy&8) b<<=1;
24069
24070 //bool bridgedetected = false;
24071
24072 int32_t walk = c.walk;
24073 if (get_bit(quest_rules, qr_SMARTER_SMART_SCROLL))
24074 {
24075 for (int32_t m = 0; m <= 1; m++)
24076 {
24077 newcombo const& cmb = combobuf[MAPCOMBO3(map, screen, m,cx,cy, true)];
24078 if (cmb.type == cBRIDGE)
24079 {
24080 if (!get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
24081 {
24082 int efflag = (cmb.walk & 0xF0)>>4;
24083 int newsolid = (cmb.walk & 0xF);
24084 walk = ((newsolid | walk) & (~efflag)) | (newsolid & efflag);
24085 }
24086 else walk &= cmb.walk;
24087 }
24088 else walk |= cmb.walk;
24089 }
24090 }
24091 /*
24092 if (bridgedetected)
24093 {
24094 continue;
24095 }*/
24096
24097 //bool swim = iswater_type(c.type) && (current_item(itype_flippers) || action==rafting);
24098 bool swim = iswaterex(MAPCOMBO3(map, screen, -1,cx,cy, get_bit(quest_rules, qr_SMARTER_SMART_SCROLL)), map, screen, -1, cx, cy, true, false, true) && (current_item(itype_flippers) || action==rafting);
24099
24100 if((walk&b) && !swim)
24101 {
24102 return true;
24103 }
24104 }
24105
24106 /*
24107 #if 0
24108
24109 //
24110 // next block (i.e. cnt==2)
24111 if(!(cx&8))
24112 {
24113 b<<=2;
24114 }
24115 else
24116 {
24117 c = combobuf[TheMaps[ns].data[++cmb]];
24118 dried = iswater_type(c.type) && DRIEDLAKE;
24119 //swim = iswater_type(c.type) && (current_item(itype_flippers));
24120 b=1;
24121
24122 if(cy&8)
24123 {
24124 b<<=1;
24125 }
24126 }
24127
24128 swim = iswaterex(c, map, screen, -1, cx+8, cy, true, false, true) && current_item(itype_flippers);
24129
24130 if((c.walk&b) && !dried && !swim)
24131 {
24132 return true;
24133 }
24134
24135 cx+=8;
24136
24137 if(cx&7)
24138 {
24139 if(!(cx&8))
24140 {
24141 b<<=2;
24142 }
24143 else
24144 {
24145 c = combobuf[TheMaps[ns].data[++cmb]];
24146 dried = iswater_type(c.type) && DRIEDLAKE;
24147 //swim = iswaterex(cmb, map, screen, -1, cx+8, cy, true, false, true) && current_item(itype_flippers);
24148 b=1;
24149
24150 if(cy&8)
24151 {
24152 b<<=1;
24153 }
24154 }
24155
24156 swim = iswaterex(c, map, screen, -1, cx+8, cy, true, false, true) && current_item(itype_flippers);
24157
24158 if((c.walk&b) && !dried && !swim)
24159 return true;
24160 }
24161
24162 #endif
24163 */
24164 }
24165
24166 return false;
24167 }
24168
24169 1888 void HeroClass::checkscroll()
24170 {
24171 //DO NOT scroll if Hero is vibrating due to Farore's Wind effect -DD
24172
2/4
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
1888 if(action == casting||action==sideswimcasting)
24173 return;
24174
24175
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(toogam)
24176 {
24177 if(x<0 && (currscr&15)==0) x=0;
24178
24179 if(y<0 && currscr<16) y=0;
24180
24181 if(x>240 && (currscr&15)==15) x=240;
24182
24183 if(y>160 && currscr>=112) y=160;
24184 }
24185
24186
2/2
✓ Branch 0 taken 1887 times.
✓ Branch 1 taken 1 times.
1888 if(y<0)
24187 {
24188 1 bool doit=true;
24189 1 y=0;
24190
24191
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if((z > 0 || fakez > 0 || stomping) && get_bit(quest_rules, qr_NO_SCROLL_WHILE_IN_AIR))
24192 doit = false;
24193
24194
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(nextcombo_wf(up))
24195 doit=false;
24196
24197
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1 if(get_bit(quest_rules, qr_SMARTSCREENSCROLL)&&(!(tmpscr->flags&fMAZE))&&action!=inwind &&action!=scrolling && !(tmpscr->flags2&wfUP))
24198 {
24199 if(nextcombo_solid(up))
24200 doit=false;
24201 }
24202
24203
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if(doit || action==inwind)
24204 {
24205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(currscr>=128)
24206 {
24207 if(specialcave >= GUYCAVE)
24208 exitcave();
24209 else stepout();
24210 }
24211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if(action==inwind)
24212 {
24213 if(DMaps[currdmap].flags&dmfWHIRLWINDRET)
24214 {
24215 action=none; FFCore.setHeroAction(none);
24216 restart_level();
24217 }
24218 else
24219 {
24220 dowarp(2,up);
24221 }
24222 }
24223
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 else if(tmpscr->flags2&wfUP && (!(tmpscr->flags8&fMAZEvSIDEWARP) || checkmaze(tmpscr,false)))
24224 {
24225 sdir=up;
24226 dowarp(1,(tmpscr->sidewarpindex)&3);
24227 }
24228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if(!edge_of_dmap(up))
24229 {
24230 1 scrolling_map = currmap;
24231 1 scrollscr(up);
24232
24233
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(tmpscr->flags4&fAUTOSAVE)
24234 {
24235 save_game(true,0);
24236 }
24237
24238
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(tmpscr->flags6&fCONTINUEHERE)
24239 {
24240 lastentrance_dmap = currdmap;
24241 lastentrance = homescr;
24242 }
24243 1 }
24244 1 }
24245 1 }
24246
24247
2/2
✓ Branch 0 taken 1887 times.
✓ Branch 1 taken 1 times.
1888 if(y>160)
24248 {
24249 1 bool doit=true;
24250 1 y=160;
24251
24252
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if((z > 0 || fakez > 0 || stomping) && get_bit(quest_rules, qr_NO_SCROLL_WHILE_IN_AIR))
24253 doit = false;
24254
24255
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(nextcombo_wf(down))
24256 doit=false;
24257
24258
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1 if(get_bit(quest_rules, qr_SMARTSCREENSCROLL)&&(!(tmpscr->flags&fMAZE))&&action!=inwind &&action!=scrolling &&!(tmpscr->flags2&wfDOWN))
24259 {
24260 if(nextcombo_solid(down))
24261 doit=false;
24262 }
24263
24264
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if(doit || action==inwind)
24265 {
24266
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(currscr>=128)
24267 {
24268
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(specialcave >= GUYCAVE)
24269 1 exitcave();
24270 else stepout();
24271 1 }
24272 else if(action==inwind)
24273 {
24274 if(DMaps[currdmap].flags&dmfWHIRLWINDRET)
24275 {
24276 action=none; FFCore.setHeroAction(none);
24277 restart_level();
24278 }
24279 else
24280 {
24281 dowarp(2,down);
24282 }
24283 }
24284 else if(tmpscr->flags2&wfDOWN && (!(tmpscr->flags8&fMAZEvSIDEWARP) || checkmaze(tmpscr,false)))
24285 {
24286 sdir=down;
24287 dowarp(1,(tmpscr->sidewarpindex>>2)&3);
24288 }
24289 else if(!edge_of_dmap(down))
24290 {
24291 scrolling_map = currmap;
24292 scrollscr(down);
24293
24294 if(tmpscr->flags4&fAUTOSAVE)
24295 {
24296 save_game(true,0);
24297 }
24298
24299 if(tmpscr->flags6&fCONTINUEHERE)
24300 {
24301 lastentrance_dmap = currdmap;
24302 lastentrance = homescr;
24303 }
24304 }
24305 1 }
24306 1 }
24307
24308
2/2
✓ Branch 0 taken 1887 times.
✓ Branch 1 taken 1 times.
1888 if(x<0)
24309 {
24310 1 bool doit=true;
24311 1 x=0;
24312
24313
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if((z > 0 || fakez > 0 || stomping) && get_bit(quest_rules, qr_NO_SCROLL_WHILE_IN_AIR))
24314 doit = false;
24315
24316
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(nextcombo_wf(left))
24317 doit=false;
24318
24319
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1 if(get_bit(quest_rules, qr_SMARTSCREENSCROLL)&&(!(tmpscr->flags&fMAZE))&&action!=inwind &&action!=scrolling &&!(tmpscr->flags2&wfLEFT))
24320 {
24321 if(nextcombo_solid(left))
24322 doit=false;
24323 }
24324
24325
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if(doit || action==inwind)
24326 {
24327
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(currscr>=128)
24328 {
24329 if(specialcave >= GUYCAVE)
24330 exitcave();
24331 else stepout();
24332 }
24333
24334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(action==inwind)
24335 {
24336 if(DMaps[currdmap].flags&dmfWHIRLWINDRET)
24337 {
24338 action=none; FFCore.setHeroAction(none);
24339 restart_level();
24340 }
24341 else
24342 {
24343 dowarp(2,left);
24344 }
24345 }
24346
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 else if(tmpscr->flags2&wfLEFT && (!(tmpscr->flags8&fMAZEvSIDEWARP) || checkmaze(tmpscr,false)))
24347 {
24348 sdir=left;
24349 dowarp(1,(tmpscr->sidewarpindex>>4)&3);
24350 }
24351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if(!edge_of_dmap(left))
24352 {
24353 1 scrolling_map = currmap;
24354 1 scrollscr(left);
24355
24356
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(tmpscr->flags4&fAUTOSAVE)
24357 {
24358 save_game(true,0);
24359 }
24360
24361
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(tmpscr->flags6&fCONTINUEHERE)
24362 {
24363 lastentrance_dmap = currdmap;
24364 lastentrance = homescr;
24365 }
24366 1 }
24367 1 }
24368 1 }
24369
24370
2/2
✓ Branch 0 taken 1887 times.
✓ Branch 1 taken 1 times.
1888 if(x>240)
24371 {
24372 1 bool doit=true;
24373 1 x=240;
24374
24375
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if((z > 0 || fakez > 0 || stomping) && get_bit(quest_rules, qr_NO_SCROLL_WHILE_IN_AIR))
24376 doit = false;
24377
24378
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(nextcombo_wf(right))
24379 doit=false;
24380
24381
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1 if(get_bit(quest_rules, qr_SMARTSCREENSCROLL)&&(!(tmpscr->flags&fMAZE))&&action!=inwind &&action!=scrolling &&!(tmpscr->flags2&wfRIGHT))
24382 {
24383 if(nextcombo_solid(right))
24384 doit=false;
24385 }
24386
24387
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if(doit || action==inwind)
24388 {
24389
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(currscr>=128)
24390 {
24391 if(specialcave >= GUYCAVE)
24392 exitcave();
24393 else stepout();
24394 }
24395
24396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(action==inwind)
24397 {
24398 if(DMaps[currdmap].flags&dmfWHIRLWINDRET)
24399 {
24400 action=none; FFCore.setHeroAction(none);
24401 restart_level();
24402 }
24403 else
24404 {
24405 dowarp(2,right);
24406 }
24407 }
24408
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 else if(tmpscr->flags2&wfRIGHT && (!(tmpscr->flags8&fMAZEvSIDEWARP) || checkmaze(tmpscr,false)))
24409 {
24410 sdir=right;
24411 dowarp(1,(tmpscr->sidewarpindex>>6)&3);
24412 }
24413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if(!edge_of_dmap(right))
24414 {
24415 1 scrolling_map = currmap;
24416 1 scrollscr(right);
24417
24418
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(tmpscr->flags4&fAUTOSAVE)
24419 {
24420 save_game(true,0);
24421 }
24422
24423
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(tmpscr->flags6&fCONTINUEHERE)
24424 {
24425 lastentrance_dmap = currdmap;
24426 lastentrance = homescr;
24427 }
24428 1 }
24429 1 }
24430 1 }
24431 1888 }
24432
24433 // assumes current direction is in lastdir[3]
24434 // compares directions with scr->path and scr->exitdir
24435 9 bool HeroClass::checkmaze(mapscr *scr, bool sound)
24436 {
24437
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if(!(scr->flags&fMAZE))
24438 9 return true;
24439
24440 if(lastdir[3]==scr->exitdir)
24441 return true;
24442
24443 for(int32_t i=0; i<4; i++)
24444 if(lastdir[i]!=scr->path[i])
24445 return false;
24446
24447 if(sound)
24448 sfx(scr->secretsfx);
24449
24450 return true;
24451 9 }
24452
24453 6 bool HeroClass::edge_of_dmap(int32_t side)
24454 {
24455
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if(checkmaze(tmpscr,false)==false)
24456 return false;
24457
24458 // needs fixin'
24459 // should check dmap style
24460
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
6 switch(side)
24461 {
24462 case up:
24463 2 return currscr<16;
24464
24465 case down:
24466 return currscr>=112;
24467
24468 case left:
24469
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if((currscr&15)==0)
24470 return true;
24471
24472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if((DMaps[currdmap].type&dmfTYPE)!=dmOVERW)
24473 // if(dlevel)
24474 return (((currscr&15)-DMaps[currdmap].xoff)<=0);
24475
24476 2 break;
24477
24478 case right:
24479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if((currscr&15)==15)
24480 return true;
24481
24482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if((DMaps[currdmap].type&dmfTYPE)!=dmOVERW)
24483 // if(dlevel)
24484 return (((currscr&15)-DMaps[currdmap].xoff)>=7);
24485
24486 2 break;
24487 }
24488
24489 4 return false;
24490 6 }
24491
24492 bool HeroClass::lookaheadraftflag(int32_t d2)
24493 {
24494 // Helper for scrollscr that gets next combo on next screen.
24495 // Can use destscr for scrolling warps,
24496 // but assumes currmap is correct.
24497
24498 int32_t cx = x;
24499 int32_t cy = y + 8;
24500
24501 bound(cx, 0, 240); //Fix crash during screen scroll when Hero is moving too quickly through a corner - DarkDragon
24502 bound(cy, 0, 168); //Fix crash during screen scroll when Hero is moving too quickly through a corner - DarkDragon
24503 //y+8 could be 168 //Attempt to fix a frash where scrolling through the lower-left corner could crassh ZC as reported by Lut. -Z
24504 //Applying this here, too. -Z
24505
24506 switch(d2)
24507 {
24508 case up:
24509 cy=160;
24510 break;
24511
24512 case down:
24513 cy=0;
24514 break;
24515
24516 case left:
24517 cx=240;
24518 break;
24519
24520 case right:
24521 cx=0;
24522 break;
24523 }
24524
24525 int32_t combo = (cy&0xF0)+(cx>>4);
24526
24527 if(combo>175)
24528 return 0;
24529 return ( isRaftFlag(combobuf[tmpscr[0].data[combo]].flag) || isRaftFlag(tmpscr[0].sflag[combo]));
24530
24531 }
24532 3 int32_t HeroClass::lookahead(int32_t d2) // Helper for scrollscr that gets next combo on next screen.
24533 {
24534 // Can use destscr for scrolling warps,
24535 // but assumes currmap is correct.
24536
24537 3 int32_t cx = vbound(x,0,240); //var = vbound(val, n1, n2), not bound(var, n1, n2) -Z
24538 3 int32_t cy = vbound(y + 8,0,160);
24539 //bound(cx, 0, 240); //Fix crash during screen scroll when Hero is moving too quickly through a corner - DarkDragon
24540 //bound(cy, 0, 168); //Fix crash during screen scroll when Hero is moving too quickly through a corner - DarkDragon
24541 //y+8 could be 168 //Attempt to fix a frash where scrolling through the lower-left corner could crassh ZC as reported by Lut. -Z
24542
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
3 switch(d2)
24543 {
24544 case up:
24545 1 cy=160;
24546 1 break;
24547
24548 case down:
24549 cy=0;
24550 break;
24551
24552 case left:
24553 1 cx=240;
24554 1 break;
24555
24556 case right:
24557 1 cx=0;
24558 1 break;
24559 }
24560
24561 3 int32_t combo = (cy&0xF0)+(cx>>4);
24562
24563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(combo>175)
24564 return 0;
24565
24566 3 return tmpscr[0].data[combo]; // entire combo code
24567 3 }
24568
24569 3 int32_t HeroClass::lookaheadflag(int32_t d2)
24570 {
24571 // Helper for scrollscr that gets next combo on next screen.
24572 // Can use destscr for scrolling warps,
24573 // but assumes currmap is correct.
24574
24575 3 int32_t cx = vbound(x,0,240);
24576 3 int32_t cy = vbound(y + 8,0,160);
24577
24578 //bound(cx, 0, 240); //Fix crash during screen scroll when Hero is moving too quickly through a corner - DarkDragon
24579 //bound(cy, 0, 168); //Fix crash during screen scroll when Hero is moving too quickly through a corner - DarkDragon
24580 //y+8 could be 168 //Attempt to fix a frash where scrolling through the lower-left corner could crassh ZC as reported by Lut. -Z
24581 //Applying this here, too. -Z
24582
24583
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
3 switch(d2)
24584 {
24585 case up:
24586 1 cy=160;
24587 1 break;
24588
24589 case down:
24590 cy=0;
24591 break;
24592
24593 case left:
24594 1 cx=240;
24595 1 break;
24596
24597 case right:
24598 1 cx=0;
24599 1 break;
24600 }
24601
24602 3 int32_t combo = (cy&0xF0)+(cx>>4);
24603
24604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(combo>175)
24605 return 0;
24606
24607
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(!tmpscr[0].sflag[combo])
24608 {
24609 3 return combobuf[tmpscr[0].data[combo]].flag; // flag
24610 }
24611
24612 return tmpscr[0].sflag[combo]; // flag
24613 3 }
24614
24615 //Bit of a messy kludge to give the correct Hero->X/Hero->Y in the script
24616 362 void HeroClass::run_scrolling_script(int32_t scrolldir, int32_t cx, int32_t sx, int32_t sy, bool end_frames, bool waitdraw)
24617 {
24618 // For rafting (and possibly other esoteric things)
24619 // Hero's action should remain unchanged while scrolling,
24620 // but for the sake of scripts, here's an eye-watering kludge.
24621 362 actiontype lastaction = action;
24622 362 action=scrolling; FFCore.setHeroAction(scrolling);
24623
2/2
✓ Branch 0 taken 181 times.
✓ Branch 1 taken 181 times.
362 if(waitdraw)
24624 {
24625 181 FFCore.runGenericPassiveEngine(SCR_TIMING_WAITDRAW);
24626 181 }
24627 else
24628 {
24629 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_FFCS-1);
24630 }
24631 362 zfix storex = x, storey = y;
24632
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 132 times.
✓ Branch 4 taken 132 times.
362 switch(scrolldir)
24633 {
24634 case up:
24635
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 9 times.
98 if(y < 160) y = 176;
24636
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
9 else if(cx > 0 && !end_frames) y = sy + 156;
24637 2 else y = 160;
24638
24639 98 break;
24640
24641 case down:
24642 if(y > 0) y = -16;
24643 else if(cx > 0 && !end_frames) y = sy - 172;
24644 else y = 0;
24645
24646 break;
24647
24648 case left:
24649
2/2
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 11 times.
132 if(x < 240) x = 256;
24650
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 else if(cx > 0) x = sx + 236;
24651 2 else x = 240;
24652
24653 132 break;
24654
24655 case right:
24656
2/2
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 11 times.
132 if(x > 0) x = -16;
24657
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 else if(cx > 0) x = sx - 252;
24658 2 else x = 0;
24659
24660 132 break;
24661 }
24662
2/2
✓ Branch 0 taken 181 times.
✓ Branch 1 taken 181 times.
362 if(waitdraw)
24663 {
24664
2/4
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 181 times.
✗ Branch 3 not taken.
181 if((!( FFCore.system_suspend[susptGLOBALGAME] )) && (global_wait & (1<<GLOBAL_SCRIPT_GAME)))
24665 {
24666 ZScriptVersion::RunScript(SCRIPT_GLOBAL, GLOBAL_SCRIPT_GAME, GLOBAL_SCRIPT_GAME);
24667 global_wait&= ~(1<<GLOBAL_SCRIPT_GAME);
24668 }
24669 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_GLOBAL_WAITDRAW);
24670
2/6
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 181 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
181 if ( (!( FFCore.system_suspend[susptHEROACTIVE] )) && player_waitdraw && FFCore.getQuestHeaderInfo(vZelda) >= 0x255 )
24671 {
24672 ZScriptVersion::RunScript(SCRIPT_PLAYER, SCRIPT_PLAYER_ACTIVE, SCRIPT_PLAYER_ACTIVE);
24673 player_waitdraw = false;
24674 }
24675 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_PLAYER_WAITDRAW);
24676
2/6
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 181 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
181 if ( (!( FFCore.system_suspend[susptDMAPSCRIPT] )) && dmap_waitdraw && FFCore.getQuestHeaderInfo(vZelda) >= 0x255 )
24677 {
24678 ZScriptVersion::RunScript(SCRIPT_DMAP, DMaps[currdmap].script,currdmap);
24679 dmap_waitdraw = false;
24680 }
24681 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_DMAPDATA_ACTIVE_WAITDRAW);
24682
2/6
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 181 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
181 if ( (!( FFCore.system_suspend[susptDMAPSCRIPT] )) && passive_subscreen_waitdraw && FFCore.getQuestHeaderInfo(vZelda) >= 0x255 )
24683 {
24684 ZScriptVersion::RunScript(SCRIPT_PASSIVESUBSCREEN, DMaps[currdmap].passive_sub_script,currdmap);
24685 passive_subscreen_waitdraw = false;
24686 }
24687 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_DMAPDATA_PASSIVESUBSCREEN_WAITDRAW);
24688
2/10
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 181 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
181 if ( (!( FFCore.system_suspend[susptSCREENSCRIPTS] )) && tmpscr->script != 0 && tmpscr->screen_waitdraw && tmpscr->preloadscript && FFCore.getQuestHeaderInfo(vZelda) >= 0x255 )
24689 {
24690 ZScriptVersion::RunScript(SCRIPT_SCREEN, tmpscr->script, 0);
24691 tmpscr->screen_waitdraw = 0;
24692 }
24693 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_SCREEN_WAITDRAW);
24694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
181 if ( !FFCore.system_suspend[susptITEMSCRIPTENGINE] )
24695 {
24696 181 FFCore.itemScriptEngineOnWaitdraw();
24697 181 }
24698 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_ITEM_WAITDRAW);
24699 181 }
24700 else
24701 {
24702
2/8
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 181 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
181 if ( (!( FFCore.system_suspend[susptSCREENSCRIPTS] )) && tmpscr->script != 0 && tmpscr->preloadscript && FFCore.getQuestHeaderInfo(vZelda) >= 0x255 )
24703 {
24704 ZScriptVersion::RunScript(SCRIPT_SCREEN, tmpscr->script, 0);
24705 }
24706 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_FFCS);
24707
2/4
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 181 times.
✗ Branch 3 not taken.
181 if((!( FFCore.system_suspend[susptGLOBALGAME] )) && (g_doscript & (1<<GLOBAL_SCRIPT_GAME)))
24708 {
24709 ZScriptVersion::RunScript(SCRIPT_GLOBAL, GLOBAL_SCRIPT_GAME, GLOBAL_SCRIPT_GAME);
24710 }
24711 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_GLOBAL_ACTIVE);
24712
3/6
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 181 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 181 times.
✗ Branch 5 not taken.
181 if ((!( FFCore.system_suspend[susptHEROACTIVE] )) && player_doscript && FFCore.getQuestHeaderInfo(vZelda) >= 0x255)
24713 {
24714 ZScriptVersion::RunScript(SCRIPT_PLAYER, SCRIPT_PLAYER_ACTIVE, SCRIPT_PLAYER_ACTIVE);
24715 }
24716 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_PLAYER_ACTIVE);
24717
3/6
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 181 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 181 times.
✗ Branch 5 not taken.
181 if ( (!( FFCore.system_suspend[susptDMAPSCRIPT] )) && dmap_doscript && FFCore.getQuestHeaderInfo(vZelda) >= 0x255 )
24718 {
24719 ZScriptVersion::RunScript(SCRIPT_DMAP, DMaps[currdmap].script,currdmap);
24720 }
24721 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_DMAPDATA_ACTIVE);
24722
3/6
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 181 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 181 times.
✗ Branch 5 not taken.
181 if ( (!( FFCore.system_suspend[susptDMAPSCRIPT] )) && passive_subscreen_doscript && FFCore.getQuestHeaderInfo(vZelda) >= 0x255 )
24723 {
24724 ZScriptVersion::RunScript(SCRIPT_PASSIVESUBSCREEN, DMaps[currdmap].passive_sub_script,currdmap);
24725 }
24726 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_DMAPDATA_PASSIVESUBSCREEN);
24727 181 bool old = get_bit(quest_rules, qr_OLD_ITEMDATA_SCRIPT_TIMING);
24728
2/4
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 181 times.
181 if(!FFCore.system_suspend[susptITEMSCRIPTENGINE] && old)
24729 181 FFCore.itemScriptEngine();
24730 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_OLD_ITEMDATA_SCRIPT);
24731
2/4
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 181 times.
✗ Branch 3 not taken.
181 if(!FFCore.system_suspend[susptITEMSCRIPTENGINE] && !old)
24732 FFCore.itemScriptEngine();
24733 }
24734
24735 362 x = storex, y = storey;
24736
24737 362 action=lastaction; FFCore.setHeroAction(lastaction);
24738 362 }
24739
24740 //Has solving the maze enabled a side warp?
24741 //Only used just before scrolling screens
24742 // Note: since scrollscr() calls this, and dowarp() calls scrollscr(),
24743 // return true to abort the topmost scrollscr() call. -L
24744 3 bool HeroClass::maze_enabled_sizewarp(int32_t scrolldir)
24745 {
24746
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 for(int32_t i = 0; i < 3; i++) lastdir[i] = lastdir[i+1];
24747
24748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 lastdir[3] = tmpscr->flags&fMAZE ? scrolldir : 0xFF;
24749
24750
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3 if(tmpscr->flags8&fMAZEvSIDEWARP && tmpscr->flags&fMAZE && scrolldir != tmpscr->exitdir)
24751 {
24752 switch(scrolldir)
24753 {
24754 case up:
24755 if(tmpscr->flags2&wfUP && checkmaze(tmpscr,true))
24756 {
24757 lastdir[3] = 0xFF;
24758 sdir=up;
24759 dowarp(1,(tmpscr->sidewarpindex)&3);
24760 return true;
24761 }
24762
24763 break;
24764
24765 case down:
24766 if(tmpscr->flags2&wfDOWN && checkmaze(tmpscr,true))
24767 {
24768 lastdir[3] = 0xFF;
24769 sdir=down;
24770 dowarp(1,(tmpscr->sidewarpindex>>2)&3);
24771 return true;
24772 }
24773
24774 break;
24775
24776 case left:
24777 if(tmpscr->flags2&wfLEFT && checkmaze(tmpscr,true))
24778 {
24779 lastdir[3] = 0xFF;
24780 sdir=left;
24781 dowarp(1,(tmpscr->sidewarpindex>>4)&3);
24782 return true;
24783 }
24784
24785 break;
24786
24787 case right:
24788 if(tmpscr->flags2&wfRIGHT && checkmaze(tmpscr,true))
24789 {
24790 lastdir[3] = 0xFF;
24791 sdir=right;
24792 dowarp(1,(tmpscr->sidewarpindex)&3);
24793 return true;
24794 }
24795
24796 break;
24797 }
24798 }
24799
24800 3 return false;
24801 3 }
24802
24803 3 int32_t HeroClass::get_scroll_step(int32_t scrolldir)
24804 {
24805 // For side-scrollers, where the relative speed of 'fast' scrolling is a bit slow.
24806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(get_bit(quest_rules, qr_VERYFASTSCROLLING))
24807 return 16;
24808
24809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(get_bit(quest_rules, qr_SMOOTHVERTICALSCROLLING) != 0)
24810 {
24811 return (isdungeon() && !get_bit(quest_rules,qr_FASTDNGN)) ? 2 : 4;
24812 }
24813 else
24814 {
24815
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
3 if(scrolldir == up || scrolldir == down)
24816 {
24817 1 return 8;
24818 }
24819 else
24820 {
24821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 return (isdungeon() && !get_bit(quest_rules,qr_FASTDNGN)) ? 2 : 4;
24822 }
24823 }
24824 3 }
24825
24826 3 int32_t HeroClass::get_scroll_delay(int32_t scrolldir)
24827 {
24828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(get_bit(quest_rules, qr_NOSCROLL))
24829 return 0;
24830
24831
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if( (get_bit(quest_rules, qr_VERYFASTSCROLLING) != 0) ||
24832 3 (get_bit(quest_rules, qr_SMOOTHVERTICALSCROLLING) != 0) )
24833 {
24834 return 1;
24835 }
24836 else
24837 {
24838
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
3 if(scrolldir == up || scrolldir == down)
24839 {
24840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 return (isdungeon() && !get_bit(quest_rules,qr_FASTDNGN)) ? 4 : 2;
24841 }
24842 else
24843 {
24844 2 return 1;
24845 }
24846 }
24847 3 }
24848
24849 void HeroClass::calc_darkroom_hero(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
24850 {
24851 int32_t itemid = current_item_id(itype_lantern);
24852 if(itemid < 0) return; //no lantern light circle
24853 int32_t hx1 = x.getInt() - x1 + 8;
24854 int32_t hy1 = y.getInt() - y1 + 8;
24855 int32_t hx2 = x.getInt() - x2 + 8;
24856 int32_t hy2 = y.getInt() - y2 + 8;
24857
24858 itemdata& lamp = itemsbuf[itemid];
24859 switch(lamp.misc1) //Shape
24860 {
24861 case 0: //Circle
24862 doDarkroomCircle(hx1, hy1, lamp.misc2, darkscr_bmp_curscr);
24863 doDarkroomCircle(hx2, hy2, lamp.misc2, darkscr_bmp_scrollscr);
24864 break;
24865 case 1: //Lamp Cone
24866 doDarkroomCone(hx1, hy1, lamp.misc2, dir, darkscr_bmp_curscr);
24867 doDarkroomCone(hx2, hy2, lamp.misc2, dir, darkscr_bmp_scrollscr);
24868 break;
24869 }
24870 }
24871
24872 3 void HeroClass::scrollscr(int32_t scrolldir, int32_t destscr, int32_t destdmap)
24873 {
24874
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if(action==freeze||action==sideswimfreeze)
24875 {
24876 return;
24877 }
24878
24879 3 bool overlay = false;
24880
24881
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if(scrolldir >= 0 && scrolldir <= 3)
24882 {
24883 3 overlay = get_bit(&tmpscr[(currscr < 128) ? 0 : 1].sidewarpoverlayflags, scrolldir) ? true : false;
24884 3 }
24885
24886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(destdmap == -1)
24887 {
24888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(ZCMaps[currmap].tileWidth != ZCMaps[DMaps[currdmap].map].tileWidth
24889
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 || ZCMaps[currmap].tileHeight != ZCMaps[DMaps[currdmap].map].tileHeight)
24890 return;
24891 3 }
24892 else
24893 {
24894 if(ZCMaps[currmap].tileWidth != ZCMaps[DMaps[destdmap].map].tileWidth
24895 || ZCMaps[currmap].tileHeight != ZCMaps[DMaps[destdmap].map].tileHeight)
24896 return;
24897 }
24898
24899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(maze_enabled_sizewarp(scrolldir)) // dowarp() was called
24900 return;
24901
24902 3 kill_enemy_sfx();
24903 3 stop_sfx(QMisc.miscsfx[sfxLOWHEART]);
24904 3 screenscrolling = true;
24905 3 FFCore.ScrollingData[SCROLLDATA_DIR] = scrolldir;
24906
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
3 switch(scrolldir)
24907 {
24908 case up:
24909 1 FFCore.ScrollingData[SCROLLDATA_NX] = 0;
24910 1 FFCore.ScrollingData[SCROLLDATA_NY] = -176;
24911 1 FFCore.ScrollingData[SCROLLDATA_OX] = 0;
24912 1 FFCore.ScrollingData[SCROLLDATA_OY] = 0;
24913 1 break;
24914 case down:
24915 FFCore.ScrollingData[SCROLLDATA_NX] = 0;
24916 FFCore.ScrollingData[SCROLLDATA_NY] = 176;
24917 FFCore.ScrollingData[SCROLLDATA_OX] = 0;
24918 FFCore.ScrollingData[SCROLLDATA_OY] = 0;
24919 break;
24920 case left:
24921 1 FFCore.ScrollingData[SCROLLDATA_NX] = -256;
24922 1 FFCore.ScrollingData[SCROLLDATA_NY] = 0;
24923 1 FFCore.ScrollingData[SCROLLDATA_OX] = 0;
24924 1 FFCore.ScrollingData[SCROLLDATA_OY] = 0;
24925 1 break;
24926 case right:
24927 1 FFCore.ScrollingData[SCROLLDATA_NX] = 256;
24928 1 FFCore.ScrollingData[SCROLLDATA_NY] = 0;
24929 1 FFCore.ScrollingData[SCROLLDATA_OX] = 0;
24930 1 FFCore.ScrollingData[SCROLLDATA_OY] = 0;
24931 1 break;
24932 }
24933 3 FFCore.init_combo_doscript();
24934 3 tmpscr[1] = tmpscr[0];
24935
24936 3 const int32_t _mapsSize = ZCMaps[currmap].tileWidth * ZCMaps[currmap].tileHeight;
24937
24938
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 3 times.
21 for(int32_t i = 0; i < 6; i++)
24939 {
24940 18 tmpscr3[i] = tmpscr2[i];
24941 18 }
24942
24943 3 conveyclk = 2;
24944
24945 3 mapscr *newscr = &tmpscr[0];
24946 3 mapscr *oldscr = &tmpscr[1];
24947
24948 //scroll x, scroll y, old screen x, old screen y, new screen x, new screen y
24949 3 int32_t sx = 0, sy = 0, tx = 0, ty = 0, tx2 = 0, ty2 = 0;
24950 3 int32_t cx = 0;
24951 3 int32_t step = get_scroll_step(scrolldir);
24952 3 int32_t delay = get_scroll_delay(scrolldir);
24953 3 bool end_frames = false;
24954
24955 3 int32_t scx = get_bit(quest_rules,qr_FASTDNGN) ? 30 : 0;
24956
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(get_bit(quest_rules, qr_VERYFASTSCROLLING)) //just a minor adjustment.
24957 scx = 32; //for sideview very fast screolling.
24958
24959
24960 3 int32_t lastattackclk = attackclk, lastspins = spins, lastcharging = charging; bool lasttapping = tapping;
24961 3 actiontype lastaction = action;
24962 3 ALLOFF(false, false);
24963 // for now, restore Hero's previous action
24964
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(!get_bit(quest_rules, qr_SCROLLING_KILLS_CHARGE))
24965 3 attackclk = lastattackclk; spins = lastspins; charging = lastcharging; tapping = lasttapping;
24966 3 action=lastaction; FFCore.setHeroAction(lastaction);
24967
24968 3 lstep = (lstep + 6) % 12;
24969 3 cx = scx;
24970 3 FFCore.runGenericPassiveEngine(SCR_TIMING_WAITDRAW);
24971
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if((!( FFCore.system_suspend[susptGLOBALGAME] )) && (global_wait & (1<<GLOBAL_SCRIPT_GAME)))
24972 {
24973 ZScriptVersion::RunScript(SCRIPT_GLOBAL, GLOBAL_SCRIPT_GAME, GLOBAL_SCRIPT_GAME);
24974 global_wait &= ~(1<<GLOBAL_SCRIPT_GAME);
24975 }
24976 3 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_GLOBAL_WAITDRAW);
24977
2/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3 if ( (!( FFCore.system_suspend[susptHEROACTIVE] )) && player_waitdraw && FFCore.getQuestHeaderInfo(vZelda) >= 0x255 )
24978 {
24979 ZScriptVersion::RunScript(SCRIPT_PLAYER, SCRIPT_PLAYER_ACTIVE, SCRIPT_PLAYER_ACTIVE);
24980 player_waitdraw = false;
24981 }
24982 3 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_PLAYER_WAITDRAW);
24983
2/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3 if ( (!( FFCore.system_suspend[susptDMAPSCRIPT] )) && dmap_waitdraw && FFCore.getQuestHeaderInfo(vZelda) >= 0x255 )
24984 {
24985 ZScriptVersion::RunScript(SCRIPT_DMAP, DMaps[currdmap].script,currdmap);
24986 dmap_waitdraw = false;
24987 }
24988 3 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_DMAPDATA_ACTIVE_WAITDRAW);
24989
2/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3 if ( (!( FFCore.system_suspend[susptDMAPSCRIPT] )) && passive_subscreen_waitdraw && FFCore.getQuestHeaderInfo(vZelda) >= 0x255 )
24990 {
24991 ZScriptVersion::RunScript(SCRIPT_PASSIVESUBSCREEN, DMaps[currdmap].passive_sub_script,currdmap);
24992 passive_subscreen_waitdraw = false;
24993 }
24994 3 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_DMAPDATA_PASSIVESUBSCREEN_WAITDRAW);
24995
2/8
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
3 if ( (!( FFCore.system_suspend[susptSCREENSCRIPTS] )) && tmpscr->script != 0 && tmpscr->screen_waitdraw && FFCore.getQuestHeaderInfo(vZelda) >= 0x255 )
24996 {
24997 ZScriptVersion::RunScript(SCRIPT_SCREEN, tmpscr->script, 0);
24998 tmpscr->screen_waitdraw = 0;
24999 }
25000 3 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_SCREEN_WAITDRAW);
25001
25002 3 word c = tmpscr->numFFC();
25003
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 for ( word q = 0; q < c; ++q )
25004 {
25005 //Z_scripterrlog("tmpscr->ffcswaitdraw is: %d\n", tmpscr->ffcswaitdraw);
25006
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ( tmpscr->ffcswaitdraw&(1<<q) )
25007 {
25008 //Z_scripterrlog("FFC (%d) called Waitdraw()\n", q);
25009 if(tmpscr->ffcs[q].script != 0)
25010 {
25011 ZScriptVersion::RunScript(SCRIPT_FFC, tmpscr->ffcs[q].script, q);
25012 tmpscr->ffcswaitdraw &= ~(1<<q);
25013 }
25014 }
25015 3 }
25016 3 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_FFC_WAITDRAW);
25017 3 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_COMBO_WAITDRAW);
25018 //Waitdraw for item scripts.
25019 3 FFCore.itemScriptEngineOnWaitdraw();
25020 3 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_ITEM_WAITDRAW);
25021 3 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_NPC_WAITDRAW);
25022
25023 //Sprite scripts on Waitdraw
25024 3 FFCore.eweaponScriptEngineOnWaitdraw();
25025 3 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_EWPN_WAITDRAW);
25026 3 FFCore.itemSpriteScriptEngineOnWaitdraw();
25027 3 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_ITEMSPRITE_WAITDRAW);
25028
25029 //This is no longer a do-while, as the first iteration is now slightly different. -Em
25030 3 draw_screen(tmpscr,true,true);
25031
25032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(cx == scx)
25033 3 rehydratelake(false);
25034
25035 3 FFCore.runGenericPassiveEngine(SCR_TIMING_END_FRAME);
25036 3 advanceframe(true);
25037
25038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(Quit)
25039 {
25040 screenscrolling = false;
25041 return;
25042 }
25043
25044 3 ++cx;
25045
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 3 times.
96 while(cx < 32)
25046 {
25047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 if(get_bit(quest_rules,qr_FIXSCRIPTSDURINGSCROLLING))
25048 {
25049 script_drawing_commands.Clear();
25050 FFCore.runGenericPassiveEngine(SCR_TIMING_START_FRAME);
25051 ZScriptVersion::RunScrollingScript(scrolldir, cx, sx, sy, end_frames, false); //Prewaitdraw
25052 ZScriptVersion::RunScrollingScript(scrolldir, cx, sx, sy, end_frames, true); //Waitdraw
25053 }
25054 93 else FFCore.runGenericPassiveEngine(SCR_TIMING_START_FRAME);
25055 93 draw_screen(tmpscr,true,true);
25056
25057
1/2
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
93 if(cx == scx)
25058 rehydratelake(false);
25059
25060 93 FFCore.runGenericPassiveEngine(SCR_TIMING_END_FRAME);
25061 93 advanceframe(true);
25062
25063
1/2
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
93 if(Quit)
25064 {
25065 screenscrolling = false;
25066 return;
25067 }
25068
25069 93 ++cx;
25070 }
25071 3 script_drawing_commands.Clear();
25072 3 FFCore.runGenericPassiveEngine(SCR_TIMING_START_FRAME);
25073
25074
25075 //clear Hero's last hits
25076 //for ( int32_t q = 0; q < 4; q++ ) sethitHeroUID(q, 0);
25077
25078
1/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 switch(DMaps[currdmap].type&dmfTYPE)
25079 {
25080 case dmDNGN:
25081 if(!get_bit(quest_rules, qr_DUNGEONS_USE_CLASSIC_CHARTING))
25082 {
25083 markBmap(scrolldir);
25084 }
25085 break;
25086 case dmOVERW: case dmBSOVERW:
25087
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(get_bit(quest_rules, qr_NO_OVERWORLD_MAP_CHARTING))
25088 3 break;
25089 [[fallthrough]];
25090 case dmCAVE:
25091 markBmap(scrolldir);
25092 break;
25093 }
25094
25095
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(fixed_door)
25096 {
25097 unsetmapflag(mSECRET);
25098 fixed_door = false;
25099 }
25100 //Z_scripterrlog("Setting 'scrolling_scr' from %d to %d\n", scrolling_scr, currscr);
25101 3 scrolling_scr = currscr;
25102
25103
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
3 switch(scrolldir)
25104 {
25105 case up:
25106 {
25107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(destscr != -1)
25108 currscr = destscr;
25109
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 else if(checkmaze(oldscr,true) && !edge_of_dmap(scrolldir))
25110 1 currscr -= 16;
25111
25112 1 loadscr(0,destdmap,currscr,scrolldir,overlay);
25113 1 blit(scrollbuf,scrollbuf,0,0,0,176,256,176);
25114 1 putscr(scrollbuf,0,0,newscr);
25115 1 putscrdoors(scrollbuf,0,0,newscr);
25116 1 sy=176;
25117
25118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(get_bit(quest_rules, qr_SMOOTHVERTICALSCROLLING) == 0)
25119 1 sy+=3;
25120
25121 1 cx=176/step;
25122 1 FFCore.init_combo_doscript();
25123 }
25124 1 break;
25125
25126 case down:
25127 {
25128 if(destscr != -1)
25129 currscr = destscr;
25130 else if(checkmaze(oldscr,true) && !edge_of_dmap(scrolldir))
25131 currscr += 16;
25132
25133 loadscr(0,destdmap,currscr,scrolldir,overlay);
25134 putscr(scrollbuf,0,176,newscr);
25135 putscrdoors(scrollbuf,0,176,newscr);
25136 sy = 0;
25137
25138 if(get_bit(quest_rules, qr_SMOOTHVERTICALSCROLLING) == 0)
25139 sy+=3;
25140
25141 cx = 176 / step;
25142 FFCore.init_combo_doscript();
25143 }
25144 break;
25145
25146 case left:
25147 {
25148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(destscr!=-1)
25149 currscr = destscr;
25150
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 else if(checkmaze(oldscr,true) && !edge_of_dmap(scrolldir))
25151 1 --currscr;
25152
25153 1 loadscr(0,destdmap,currscr,scrolldir,overlay);
25154 1 blit(scrollbuf,scrollbuf,0,0,256,0,256,176);
25155 1 putscr(scrollbuf,0,0,newscr);
25156 1 putscrdoors(scrollbuf,0,0,newscr);
25157 1 sx = 256;
25158 1 cx = 256 / step;
25159 1 FFCore.init_combo_doscript();
25160 }
25161 1 break;
25162
25163 case right:
25164 {
25165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(destscr != -1)
25166 currscr = destscr;
25167
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 else if(checkmaze(oldscr,true) && !edge_of_dmap(scrolldir))
25168 1 ++currscr;
25169
25170 1 loadscr(0,destdmap,currscr,scrolldir,overlay);
25171 1 putscr(scrollbuf,256,0,newscr);
25172 1 putscrdoors(scrollbuf,256,0,tmpscr);
25173 1 sx = 0;
25174 1 cx = 256 / step;
25175 1 FFCore.init_combo_doscript();
25176 }
25177 1 break;
25178 }
25179
25180 // change Hero's state if entering water
25181 3 int32_t ahead = lookahead(scrolldir);
25182 3 int32_t aheadflag = lookaheadflag(scrolldir);
25183 3 int32_t lookaheadx = vbound(x+8,0,240); //var = vbound(val, n1, n2), not bound(var, n1, n2) -Z
25184 3 int32_t lookaheady = vbound(y + (bigHitbox?8:12),0,160);
25185 //bound(cx, 0, 240); //Fix crash during screen scroll when Hero is moving too quickly through a corner - DarkDragon
25186 //bound(cy, 0, 168); //Fix crash during screen scroll when Hero is moving too quickly through a corner - DarkDragon
25187 //y+8 could be 168 //Attempt to fix a frash where scrolling through the lower-left corner could crassh ZC as reported by Lut. -Z
25188
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
3 switch(scrolldir)
25189 {
25190 case up:
25191 1 lookaheady=160;
25192 1 break;
25193
25194 case down:
25195 lookaheady=0;
25196 break;
25197
25198 case left:
25199 1 lookaheadx=240;
25200 1 break;
25201
25202 case right:
25203 1 lookaheadx=0;
25204 1 break;
25205 }
25206
25207 3 bool nowinwater = false;
25208
25209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(lastaction != inwind)
25210 {
25211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(lastaction == rafting ) //&& isRaftFlag(aheadflag))
25212 {
25213 if (lookaheadraftflag(scrolldir))
25214 {
25215 action=rafting; FFCore.setHeroAction(rafting);
25216 raftclk=0;
25217 }
25218 }
25219
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 else if(iswaterex(ahead, currmap, currscr, -1, lookaheadx,lookaheady) && (current_item(itype_flippers)))
25220 {
25221 if(lastaction==swimming || lastaction == sideswimming || lastaction == sideswimattacking || lastaction == sideswimhit || lastaction == swimhit || lastaction == sideswimcasting || lastaction == sidewaterhold1 || lastaction == sidewaterhold2)
25222 {
25223 SetSwim();
25224 hopclk = 0xFF;
25225 nowinwater = true;
25226 }
25227 else
25228 {
25229 action=hopping; FFCore.setHeroAction(hopping);
25230 hopclk = 2;
25231 nowinwater = true;
25232 }
25233 }
25234
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 else if((lastaction == attacking || lastaction == sideswimattacking) && charging)
25235 {
25236 action = lastaction; FFCore.setHeroAction(lastaction);
25237 }
25238 else
25239 {
25240 3 action=none; FFCore.setHeroAction(none);
25241 }
25242 3 }
25243
25244 // The naturaldark state can be read/set by an FFC script before
25245 // fade() or lighting() is called.
25246 3 naturaldark = ((TheMaps[currmap*MAPSCRS+currscr].flags & fDARK) != 0);
25247
25248
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(newscr->oceansfx != oldscr->oceansfx) adjust_sfx(oldscr->oceansfx, 128, false);
25249
25250
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(newscr->bosssfx != oldscr->bosssfx) adjust_sfx(oldscr->bosssfx, 128, false);
25251 //Preloaded ffc scripts
25252 3 homescr=currscr;
25253 3 auto olddmap = currdmap;
25254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 auto newdmap = (destdmap >= 0) ? destdmap : currdmap;
25255
25256 3 currdmap = newdmap;
25257 3 ffscript_engine(true);
25258 3 currdmap = olddmap;
25259
25260 // There are two occasions when scrolling must be darkened:
25261 // 1) When scrolling into a dark room.
25262 // 2) When scrolling between DMaps of different colours.
25263
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if(destdmap != -1 && DMaps[destdmap].color != currcset)
25264 {
25265 fade((specialcave > 0) ? (specialcave >= GUYCAVE) ? 10 : 11 : currcset, true, false);
25266 darkroom = true;
25267 }
25268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 else if(!darkroom)
25269 3 lighting(false, false); // NES behaviour: fade to dark before scrolling
25270
25271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(action != rafting) // Is this supposed to be here?!
25272
25273 3 cx++; //This was the easiest way to re-arrange the loop so drawing is in the middle
25274
25275 3 cx *= delay; //so we can have drawing re-done every frame,
25276 //previously it was for(0 to delay) advanceframes at end of loop
25277 3 int32_t no_move = 0;
25278
25279 3 currdmap = newdmap;
25280
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 181 times.
✓ Branch 2 taken 181 times.
✓ Branch 3 taken 3 times.
184 for(word i = 0; cx >= 0 && delay != 0; i++, cx--) //Go!
25281 {
25282
2/4
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 181 times.
181 if (replay_is_active() && replay_get_version() < 3)
25283 {
25284 181 replay_poll();
25285 181 }
25286
1/2
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
181 if(Quit)
25287 {
25288 screenscrolling = false;
25289 return;
25290 }
25291
25292
25293 181 ZScriptVersion::RunScrollingScript(scrolldir, cx, sx, sy, end_frames, false);
25294
25295
2/2
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 29 times.
181 if(no_move > 0)
25296 29 no_move--;
25297
25298 //Don't want to move things on the first or last iteration, or between delays
25299
6/6
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 175 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 151 times.
181 if(i == 0 || cx == 0 || cx % delay != 0)
25300 30 no_move++;
25301
25302
3/4
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 132 times.
181 if(scrolldir == up || scrolldir == down)
25303 {
25304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if(!get_bit(quest_rules, qr_SMOOTHVERTICALSCROLLING))
25305 {
25306 //Add a few extra frames if on the second loop and cool scrolling is not set
25307
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
49 if(i == 1)
25308 {
25309 1 cx += (scrolldir == down) ? 3 : 2;
25310 1 no_move += (scrolldir == down) ? 3 : 2;
25311 1 }
25312 49 }
25313 else
25314 {
25315 //4 frames after we've finished scrolling of being still
25316 if(cx == 0 && !end_frames)
25317 {
25318 cx += 4;
25319 no_move += 4;
25320 end_frames = true;
25321 }
25322 }
25323 49 }
25324
25325 //Move Hero and the scroll position
25326
2/2
✓ Branch 0 taken 149 times.
✓ Branch 1 taken 32 times.
181 if(!no_move)
25327 {
25328
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 64 times.
149 switch(scrolldir)
25329 {
25330 case up:
25331 21 sy -= step;
25332 21 y += step;
25333 21 break;
25334
25335 case down:
25336 sy += step;
25337 y -= step;
25338 break;
25339
25340 case left:
25341 64 sx -= step;
25342 64 x += step;
25343 64 break;
25344
25345 case right:
25346 64 sx += step;
25347 64 x -= step;
25348 64 break;
25349 }
25350
25351 //bound Hero when me move him off the screen in the last couple of frames of scrolling
25352
2/2
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 1 times.
149 if(y > 160) y = 160;
25353
25354
1/2
✓ Branch 0 taken 149 times.
✗ Branch 1 not taken.
149 if(y < 0) y = 0;
25355
25356
2/2
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 4 times.
149 if(x > 240) x = 240;
25357
25358
2/2
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 4 times.
149 if(x < 0) x = 0;
25359
25360
2/4
✓ Branch 0 taken 149 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 149 times.
149 if(ladderx > 0 || laddery > 0)
25361 {
25362 // If the ladder moves on both axes, the player can
25363 // gradually shift it by going back and forth
25364 if(scrolldir==up || scrolldir==down)
25365 laddery = y.getInt();
25366 else
25367 ladderx = x.getInt();
25368 }
25369 149 }
25370
25371 //Drawing
25372 181 tx = sx;
25373 181 ty = sy;
25374 181 tx2 = sx;
25375 181 ty2 = sy;
25376
25377
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 66 times.
✓ Branch 4 taken 49 times.
181 switch(scrolldir)
25378 {
25379 case right:
25380 66 FFCore.ScrollingData[SCROLLDATA_NX] = 256-tx2;
25381 66 FFCore.ScrollingData[SCROLLDATA_NY] = 0;
25382 66 FFCore.ScrollingData[SCROLLDATA_OX] = -tx2;
25383 66 FFCore.ScrollingData[SCROLLDATA_OY] = 0;
25384 66 tx -= 256;
25385 66 break;
25386
25387 case down:
25388 FFCore.ScrollingData[SCROLLDATA_NX] = 0;
25389 FFCore.ScrollingData[SCROLLDATA_NY] = 176-ty2;
25390 FFCore.ScrollingData[SCROLLDATA_OX] = 0;
25391 FFCore.ScrollingData[SCROLLDATA_OY] = -ty2;
25392 ty -= 176;
25393 break;
25394
25395 case left:
25396 66 FFCore.ScrollingData[SCROLLDATA_NX] = -tx2;
25397 66 FFCore.ScrollingData[SCROLLDATA_NY] = 0;
25398 66 FFCore.ScrollingData[SCROLLDATA_OX] = 256-tx2;
25399 66 FFCore.ScrollingData[SCROLLDATA_OY] = 0;
25400 66 tx2 -= 256;
25401 66 break;
25402
25403 case up:
25404 49 FFCore.ScrollingData[SCROLLDATA_NX] = 0;
25405 49 FFCore.ScrollingData[SCROLLDATA_NY] = -ty2;
25406 49 FFCore.ScrollingData[SCROLLDATA_OX] = 0;
25407 49 FFCore.ScrollingData[SCROLLDATA_OY] = 176-ty2;
25408 49 ty2 -= 176;
25409 49 break;
25410 }
25411
25412 //FFScript.OnWaitdraw()
25413 181 ZScriptVersion::RunScrollingScript(scrolldir, cx, sx, sy, end_frames, true); //Waitdraw
25414
25415 181 FFCore.runGenericPassiveEngine(SCR_TIMING_PRE_DRAW);
25416 181 clear_bitmap(scrollbuf);
25417 181 clear_bitmap(framebuf);
25418
25419
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 66 times.
✓ Branch 4 taken 66 times.
181 switch(scrolldir)
25420 {
25421 case up:
25422
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if(XOR(newscr->flags7&fLAYER2BG, DMaps[currdmap].flags&dmfLAYER2BG)) do_layer(scrollbuf, 0, 2, newscr, 0, playing_field_offset, 2);
25423
25424
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if(XOR(oldscr->flags7&fLAYER2BG, DMaps[currdmap].flags&dmfLAYER2BG)) do_layer(scrollbuf, 0, 2, oldscr, 0, -176+playing_field_offset, 3);
25425
25426
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if(XOR(newscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG)) do_layer(scrollbuf, 0, 3, newscr, 0, playing_field_offset, 2);
25427
25428
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if(XOR(oldscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG)) do_layer(scrollbuf, 0, 3, oldscr, 0, -176+playing_field_offset, 3);
25429
25430 // Draw both screens' background layer primitives together, after both layers' combos.
25431 // Not ideal, but probably good enough for all realistic purposes.
25432
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
49 if(XOR((newscr->flags7&fLAYER2BG) || (oldscr->flags7&fLAYER2BG), DMaps[currdmap].flags&dmfLAYER2BG)) do_primitives(scrollbuf, 2, newscr, sx, sy);
25433
25434
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
49 if(XOR((newscr->flags7&fLAYER3BG) || (oldscr->flags7&fLAYER3BG), DMaps[currdmap].flags&dmfLAYER3BG)) do_primitives(scrollbuf, 3, newscr, sx, sy);
25435
25436 49 putscr(scrollbuf, 0, 0, newscr);
25437 49 putscr(scrollbuf, 0, 176, oldscr);
25438 49 break;
25439
25440 case down:
25441 if(XOR(newscr->flags7&fLAYER2BG, DMaps[currdmap].flags&dmfLAYER2BG)) do_layer(scrollbuf, 0, 2, newscr, 0, -176+playing_field_offset, 2);
25442
25443 if(XOR(oldscr->flags7&fLAYER2BG, DMaps[currdmap].flags&dmfLAYER2BG)) do_layer(scrollbuf, 0, 2, oldscr, 0, playing_field_offset, 3);
25444
25445 if(XOR(newscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG)) do_layer(scrollbuf, 0, 3, newscr, 0, -176+playing_field_offset, 2);
25446
25447 if(XOR(oldscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG)) do_layer(scrollbuf, 0, 3, oldscr, 0, playing_field_offset, 3);
25448
25449 if(XOR((newscr->flags7&fLAYER2BG) || (oldscr->flags7&fLAYER2BG), DMaps[currdmap].flags&dmfLAYER2BG)) do_primitives(scrollbuf, 2, newscr, sx, sy);
25450
25451 if(XOR((newscr->flags7&fLAYER3BG) || (oldscr->flags7&fLAYER3BG), DMaps[currdmap].flags&dmfLAYER3BG)) do_primitives(scrollbuf, 3, newscr, sx, sy);
25452
25453 putscr(scrollbuf, 0, 0, oldscr);
25454 putscr(scrollbuf, 0, 176, newscr);
25455 break;
25456
25457 case left:
25458
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if(XOR(newscr->flags7&fLAYER2BG, DMaps[currdmap].flags&dmfLAYER2BG)) do_layer(scrollbuf, 0, 2, newscr, 0, playing_field_offset, 2);
25459
25460
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if(XOR(oldscr->flags7&fLAYER2BG, DMaps[currdmap].flags&dmfLAYER2BG)) do_layer(scrollbuf, 0, 2, oldscr, -256, playing_field_offset, 3);
25461
25462
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if(XOR(newscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG)) do_layer(scrollbuf, 0, 3, newscr, 0, playing_field_offset, 2);
25463
25464
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if(XOR(oldscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG)) do_layer(scrollbuf, 0, 3, oldscr, -256, playing_field_offset, 3);
25465
25466
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
66 if(XOR((newscr->flags7&fLAYER2BG) || (oldscr->flags7&fLAYER2BG), DMaps[currdmap].flags&dmfLAYER2BG)) do_primitives(scrollbuf, 2, newscr, sx, sy);
25467
25468
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
66 if(XOR((newscr->flags7&fLAYER3BG) || (oldscr->flags7&fLAYER3BG), DMaps[currdmap].flags&dmfLAYER3BG)) do_primitives(scrollbuf, 3, newscr, sx, sy);
25469
25470 66 putscr(scrollbuf, 0, 0, newscr);
25471 66 putscr(scrollbuf, 256, 0, oldscr);
25472 66 break;
25473
25474 case right:
25475
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if(XOR(newscr->flags7&fLAYER2BG, DMaps[currdmap].flags&dmfLAYER2BG)) do_layer(scrollbuf, 0, 2, newscr, -256, playing_field_offset, 2);
25476
25477
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if(XOR(oldscr->flags7&fLAYER2BG, DMaps[currdmap].flags&dmfLAYER2BG)) do_layer(scrollbuf, 0, 2, oldscr, 0, playing_field_offset, 3);
25478
25479
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if(XOR(newscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG)) do_layer(scrollbuf, 0, 3, newscr, -256, playing_field_offset, 2);
25480
25481
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if(XOR(oldscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG)) do_layer(scrollbuf, 0, 3, oldscr, 0, playing_field_offset, 3);
25482
25483
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
66 if(XOR((newscr->flags7&fLAYER2BG) || (oldscr->flags7&fLAYER2BG), DMaps[currdmap].flags&dmfLAYER2BG)) do_primitives(scrollbuf, 2, newscr, sx, sy);
25484
25485
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
66 if(XOR((newscr->flags7&fLAYER3BG) || (oldscr->flags7&fLAYER3BG), DMaps[currdmap].flags&dmfLAYER3BG)) do_primitives(scrollbuf, 3, newscr, sx, sy);
25486
25487 66 putscr(scrollbuf, 0, 0, oldscr);
25488 66 putscr(scrollbuf, 256, 0, newscr);
25489 66 break;
25490 }
25491
25492 181 blit(scrollbuf, framebuf, sx, sy, 0, playing_field_offset, 256, 168);
25493 181 do_primitives(framebuf, 0, newscr, 0, playing_field_offset);
25494
25495 181 do_layer(framebuf, 0, 1, oldscr, tx2, ty2, 3);
25496 181 do_layer(framebuf, 0, 1, newscr, tx, ty, 2, false, true);
25497
25498
1/2
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
181 if(get_bit(quest_rules, qr_FFCSCROLL))
25499 {
25500 do_layer(framebuf, -3, 0, oldscr, tx2, ty2, 3, true); //ffcs
25501 do_layer(framebuf, -3, 0, newscr, tx, ty, 2, true);
25502 }
25503
25504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
181 if(!(XOR(oldscr->flags7&fLAYER2BG, DMaps[currdmap].flags&dmfLAYER2BG)) ) do_layer(framebuf, 0, 2, oldscr, tx2, ty2, 3);
25505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
181 if(!(XOR(newscr->flags7&fLAYER2BG, DMaps[currdmap].flags&dmfLAYER2BG))) do_layer(framebuf, 0, 2, newscr, tx, ty, 2, false, !(oldscr->flags7&fLAYER2BG));
25506
25507 //push blocks
25508 181 do_layer(framebuf, -2, 0, oldscr, tx2, ty2, 3);
25509 181 do_layer(framebuf, -2, 0, newscr, tx, ty, 2);
25510
1/2
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
181 if(get_bit(quest_rules, qr_PUSHBLOCK_LAYER_1_2))
25511 {
25512 do_layer(framebuf, -2, 1, oldscr, tx2, ty2, 3);
25513 do_layer(framebuf, -2, 1, newscr, tx, ty, 2);
25514 do_layer(framebuf, -2, 2, oldscr, tx2, ty2, 3);
25515 do_layer(framebuf, -2, 2, newscr, tx, ty, 2);
25516 }
25517
25518 181 do_walkflags(framebuf, oldscr, tx2, ty2,3); //show walkflags if the cheat is on
25519 181 do_walkflags(framebuf, newscr, tx, ty,2);
25520
25521 181 do_effectflags(framebuf, oldscr, tx2, ty2,3); //show effectflags if the cheat is on
25522 181 do_effectflags(framebuf, newscr, tx, ty,2);
25523
25524
25525 181 putscrdoors(framebuf, 0-tx2, 0-ty2+playing_field_offset, oldscr);
25526 181 putscrdoors(framebuf, 0-tx, 0-ty+playing_field_offset, newscr);
25527 181 herostep();
25528
25529
4/6
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 181 times.
✓ Branch 4 taken 181 times.
✓ Branch 5 taken 181 times.
181 if((z > 0 || fakez > 0) && (!get_bit(quest_rules,qr_SHADOWSFLICKER) || frame&1))
25530 {
25531 362 drawshadow(framebuf, get_bit(quest_rules, qr_TRANSSHADOWS) != 0);
25532 362 }
25533
25534
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
181 if(!isdungeon() || get_bit(quest_rules,qr_FREEFORM))
25535 {
25536 181 draw_under(framebuf); //draw the ladder or raft
25537 181 decorations.draw2(framebuf, true);
25538 181 draw(framebuf); //Hero
25539 181 decorations.draw(framebuf, true);
25540 181 }
25541
25542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
181 if(!(XOR(oldscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG))) do_layer(framebuf, 0, 3, oldscr, tx2, ty2, 3);
25543
25544 181 do_layer(framebuf, 0, 4, oldscr, tx2, ty2, 3); //layer 4
25545 181 do_layer(framebuf, -1, 0, oldscr, tx2, ty2, 3); //overhead combos
25546
1/2
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
181 if(get_bit(quest_rules, qr_OVERHEAD_COMBOS_L1_L2))
25547 {
25548 do_layer(framebuf, -1, 1, oldscr, tx2, ty2, 3); //overhead combos
25549 do_layer(framebuf, -1, 2, oldscr, tx2, ty2, 3); //overhead combos
25550 }
25551 181 do_layer(framebuf, 0, 5, oldscr, tx2, ty2, 3); //layer 5
25552 181 do_layer(framebuf, -4, 0, oldscr, tx2, ty2, 3, true); //overhead FFCs
25553 181 do_layer(framebuf, 0, 6, oldscr, tx2, ty2, 3); //layer 6
25554
25555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
181 if(!(XOR(newscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG))) do_layer(framebuf, 0, 3, newscr, tx, ty, 2, false, !(XOR(oldscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG)));
25556
25557 181 do_layer(framebuf, 0, 4, newscr, tx, ty, 2, false, true); //layer 4
25558 181 do_layer(framebuf, -1, 0, newscr, tx, ty, 2); //overhead combos
25559
1/2
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
181 if(get_bit(quest_rules, qr_OVERHEAD_COMBOS_L1_L2))
25560 {
25561 do_layer(framebuf, -1, 1, newscr, tx, ty, 2); //overhead combos
25562 do_layer(framebuf, -1, 2, newscr, tx, ty, 2); //overhead combos
25563 }
25564 181 do_layer(framebuf, 0, 5, newscr, tx, ty, 2, false, true); //layer 5
25565 181 do_layer(framebuf, -4, 0, newscr, tx, ty, 2, true); //overhead FFCs
25566 181 do_layer(framebuf, 0, 6, newscr, tx, ty, 2, false, true); //layer 6
25567
25568
25569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
181 if(msg_bg_display_buf->clip == 0)
25570 {
25571 blit_msgstr_bg(framebuf, tx2, ty2, 0, playing_field_offset, 256, 168);
25572 }
25573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
181 if(msg_portrait_display_buf->clip == 0)
25574 {
25575 blit_msgstr_prt(framebuf, tx2, ty2, 0, playing_field_offset, 256, 168);
25576 }
25577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
181 if(msg_txt_display_buf->clip == 0)
25578 {
25579 blit_msgstr_fg(framebuf, tx2, ty2, 0, playing_field_offset, 256, 168);
25580 }
25581
25582
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
181 if(get_bit(quest_rules, qr_NEW_DARKROOM) && ((newscr->flags&fDARK)||(oldscr->flags&fDARK)))
25583 {
25584 clear_to_color(darkscr_bmp_curscr, game->get_darkscr_color());
25585 clear_to_color(darkscr_bmp_curscr_trans, game->get_darkscr_color());
25586 clear_to_color(darkscr_bmp_scrollscr, game->get_darkscr_color());
25587 clear_to_color(darkscr_bmp_scrollscr_trans, game->get_darkscr_color());
25588 calc_darkroom_combos(true);
25589 calc_darkroom_hero(FFCore.ScrollingData[SCROLLDATA_NX], FFCore.ScrollingData[SCROLLDATA_NY],FFCore.ScrollingData[SCROLLDATA_OX], FFCore.ScrollingData[SCROLLDATA_OY]);
25590 }
25591
25592
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
181 if(get_bit(quest_rules, qr_NEW_DARKROOM) && get_bit(quest_rules, qr_NEWDARK_L6))
25593 {
25594 set_clip_rect(framebuf, 0, playing_field_offset, 256, 168+playing_field_offset);
25595 int32_t dx1 = FFCore.ScrollingData[SCROLLDATA_NX], dy1 = FFCore.ScrollingData[SCROLLDATA_NY]+playing_field_offset;
25596 int32_t dx2 = FFCore.ScrollingData[SCROLLDATA_OX], dy2 = FFCore.ScrollingData[SCROLLDATA_OY]+playing_field_offset;
25597 if(newscr->flags & fDARK)
25598 {
25599 if(newscr->flags9 & fDARK_DITHER) //dither the entire bitmap
25600 {
25601 ditherblit(darkscr_bmp_curscr,darkscr_bmp_curscr,0,game->get_dither_type(),game->get_dither_arg());
25602 ditherblit(darkscr_bmp_curscr_trans,darkscr_bmp_curscr_trans,0,game->get_dither_type(),game->get_dither_arg());
25603 }
25604
25605 color_map = &trans_table2;
25606 if(newscr->flags9 & fDARK_TRANS) //draw the dark as transparent
25607 draw_trans_sprite(framebuf, darkscr_bmp_curscr, dx1, dy1);
25608 else
25609 masked_blit(darkscr_bmp_curscr, framebuf, 0, 0, dx1, dy1, 256, 176);
25610 draw_trans_sprite(framebuf, darkscr_bmp_curscr_trans, dx1, dy1);
25611 color_map = &trans_table;
25612 }
25613 if(oldscr->flags & fDARK)
25614 {
25615 if(oldscr->flags9 & fDARK_DITHER) //dither the entire bitmap
25616 {
25617 ditherblit(darkscr_bmp_scrollscr,darkscr_bmp_scrollscr,0,game->get_dither_type(),game->get_dither_arg());
25618 ditherblit(darkscr_bmp_scrollscr_trans,darkscr_bmp_scrollscr_trans,0,game->get_dither_type(),game->get_dither_arg());
25619 }
25620
25621 color_map = &trans_table2;
25622 if(oldscr->flags9 & fDARK_TRANS) //draw the dark as transparent
25623 draw_trans_sprite(framebuf, darkscr_bmp_scrollscr, dx2, dy2);
25624 else
25625 masked_blit(darkscr_bmp_scrollscr, framebuf, 0, 0, dx2, dy2, 256, 176);
25626 draw_trans_sprite(framebuf, darkscr_bmp_scrollscr_trans, dx2, dy2);
25627 color_map = &trans_table;
25628 }
25629 set_clip_rect(framebuf, 0, 0, framebuf->w, framebuf->h);
25630 }
25631 181 put_passive_subscr(framebuf, &QMisc, 0, passive_subscreen_offset, game->should_show_time(), sspUP);
25632
1/2
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
181 if(get_bit(quest_rules,qr_SUBSCREENOVERSPRITES))
25633 do_primitives(framebuf, 7, newscr, 0, playing_field_offset);
25634
25635
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
181 if(get_bit(quest_rules, qr_NEW_DARKROOM) && !get_bit(quest_rules, qr_NEWDARK_L6))
25636 {
25637 set_clip_rect(framebuf, 0, playing_field_offset, 256, 168+playing_field_offset);
25638 int32_t dx1 = FFCore.ScrollingData[SCROLLDATA_NX], dy1 = FFCore.ScrollingData[SCROLLDATA_NY]+playing_field_offset;
25639 int32_t dx2 = FFCore.ScrollingData[SCROLLDATA_OX], dy2 = FFCore.ScrollingData[SCROLLDATA_OY]+playing_field_offset;
25640 if(newscr->flags & fDARK)
25641 {
25642 if(newscr->flags9 & fDARK_DITHER) //dither the entire bitmap
25643 {
25644 ditherblit(darkscr_bmp_curscr,darkscr_bmp_curscr,0,game->get_dither_type(),game->get_dither_arg());
25645 ditherblit(darkscr_bmp_curscr_trans,darkscr_bmp_curscr_trans,0,game->get_dither_type(),game->get_dither_arg());
25646 }
25647
25648 color_map = &trans_table2;
25649 if(newscr->flags9 & fDARK_TRANS) //draw the dark as transparent
25650 draw_trans_sprite(framebuf, darkscr_bmp_curscr, dx1, dy1);
25651 else
25652 masked_blit(darkscr_bmp_curscr, framebuf, 0, 0, dx1, dy1, 256, 176);
25653 draw_trans_sprite(framebuf, darkscr_bmp_curscr_trans, dx1, dy1);
25654 color_map = &trans_table;
25655 }
25656 if(oldscr->flags & fDARK)
25657 {
25658 if(oldscr->flags9 & fDARK_DITHER) //dither the entire bitmap
25659 {
25660 ditherblit(darkscr_bmp_scrollscr,darkscr_bmp_scrollscr,0,game->get_dither_type(),game->get_dither_arg());
25661 ditherblit(darkscr_bmp_scrollscr_trans,darkscr_bmp_scrollscr_trans,0,game->get_dither_type(),game->get_dither_arg());
25662 }
25663
25664 color_map = &trans_table2;
25665 if(oldscr->flags9 & fDARK_TRANS) //draw the dark as transparent
25666 draw_trans_sprite(framebuf, darkscr_bmp_scrollscr, dx2, dy2);
25667 else
25668 masked_blit(darkscr_bmp_scrollscr, framebuf, 0, 0, dx2, dy2, 256, 176);
25669 draw_trans_sprite(framebuf, darkscr_bmp_scrollscr_trans, dx2, dy2);
25670 color_map = &trans_table;
25671 }
25672 set_clip_rect(framebuf, 0, 0, framebuf->w, framebuf->h);
25673 }
25674 181 FFCore.runGenericPassiveEngine(SCR_TIMING_POST_DRAW);
25675
25676 //end drawing
25677 181 FFCore.runGenericPassiveEngine(SCR_TIMING_END_FRAME);
25678 181 advanceframe(true/*,true,false*/);
25679 181 script_drawing_commands.Clear();
25680 181 FFCore.runGenericPassiveEngine(SCR_TIMING_START_FRAME);
25681 181 actiontype lastaction = action;
25682 181 action=scrolling; FFCore.setHeroAction(scrolling);
25683 181 FFCore.runF6Engine();
25684 //FFCore.runF6EngineScrolling(newscr,oldscr,tx,ty,tx2,ty2,sx,sy,scrolldir);
25685 181 action=lastaction; FFCore.setHeroAction(lastaction);
25686 181 }//end main scrolling loop (2 spaces tab width makes me sad =( )
25687 3 currdmap = olddmap;
25688
25689 3 clear_bitmap(msg_txt_display_buf);
25690 3 set_clip_state(msg_txt_display_buf, 1);
25691 3 clear_bitmap(msg_bg_display_buf);
25692 3 set_clip_state(msg_bg_display_buf, 1);
25693 3 clear_bitmap(msg_portrait_display_buf);
25694 3 set_clip_state(msg_portrait_display_buf, 1);
25695
25696 //Move hero to the other side of the screen if scrolling's not turned on
25697
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(get_bit(quest_rules, qr_NOSCROLL))
25698 {
25699 switch(scrolldir)
25700 {
25701 case up:
25702 y = 160;
25703 break;
25704
25705 case down:
25706 y = 0;
25707 break;
25708
25709 case left:
25710 x = 240;
25711 break;
25712
25713 case right:
25714 x = 0;
25715 break;
25716 }
25717 }
25718
25719
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if((z > 0 || fakez > 0) && isSideViewHero())
25720 {
25721 y -= z;
25722 y -= fakez;
25723 z = 0;
25724 fakez = 0;
25725 }
25726
25727 3 set_respawn_point(false);
25728 3 trySideviewLadder();
25729 3 warpx = -1;
25730 3 warpy = -1;
25731
25732 3 screenscrolling = false;
25733 3 FFCore.ScrollingData[SCROLLDATA_DIR] = -1;
25734 3 FFCore.ScrollingData[SCROLLDATA_NX] = 0;
25735 3 FFCore.ScrollingData[SCROLLDATA_NY] = 0;
25736 3 FFCore.ScrollingData[SCROLLDATA_OX] = 0;
25737 3 FFCore.ScrollingData[SCROLLDATA_OY] = 0;
25738
25739
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(destdmap != -1)
25740 {
25741 bool changedlevel = false;
25742 bool changeddmap = false;
25743 if(olddmap != destdmap)
25744 {
25745 timeExitAllGenscript(GENSCR_ST_CHANGE_DMAP);
25746 changeddmap = true;
25747 }
25748 if(DMaps[olddmap].level != DMaps[destdmap].level)
25749 {
25750 timeExitAllGenscript(GENSCR_ST_CHANGE_LEVEL);
25751 changedlevel = true;
25752 }
25753 dlevel = DMaps[destdmap].level;
25754 currdmap = destdmap;
25755 if(changeddmap)
25756 {
25757 throwGenScriptEvent(GENSCR_EVENT_CHANGE_DMAP);
25758 }
25759 if(changedlevel)
25760 {
25761 throwGenScriptEvent(GENSCR_EVENT_CHANGE_LEVEL);
25762 }
25763 }
25764
25765 //if Hero is going from non-water to water, and we set his animation to "hopping" above, we must now
25766 //change it to swimming - since we have manually moved Hero onto the first tile, the hopping code
25767 //will get confused and try to hop Hero onto the next (possibly nonexistant) water tile in his current
25768 //direction. -DD
25769
25770
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(nowinwater)
25771 {
25772 SetSwim();
25773 hopclk = 0xFF;
25774 }
25775
25776 // NES behaviour: Fade to light after scrolling
25777 3 lighting(false, false); // No, we don't need to set naturaldark...
25778
25779 3 init_dmap();
25780 3 putscr(scrollbuf,0,0,newscr);
25781 3 putscrdoors(scrollbuf,0,0,newscr);
25782
25783 // Check for raft flags
25784
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
3 if(action!=rafting && hopclk==0 && !toogam)
25785 {
25786
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if(MAPFLAG(x,y)==mfRAFT||MAPCOMBOFLAG(x,y)==mfRAFT)
25787 {
25788 sfx(tmpscr->secretsfx);
25789 action=rafting; FFCore.setHeroAction(rafting);
25790 raftclk=0;
25791 }
25792
25793 // Half a tile off?
25794
6/8
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
5 else if((dir==left || dir==right) && (MAPFLAG(x,y+8)==mfRAFT||MAPCOMBOFLAG(x,y+8)==mfRAFT))
25795 {
25796 sfx(tmpscr->secretsfx);
25797 action=rafting; FFCore.setHeroAction(rafting);
25798 raftclk=0;
25799 }
25800 3 }
25801
25802 3 opendoors=0;
25803 3 markBmap(-1);
25804
25805
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(isdungeon())
25806 {
25807 switch(tmpscr->door[scrolldir^1])
25808 {
25809 case dOPEN:
25810 case dUNLOCKED:
25811 case dOPENBOSS:
25812 dir = scrolldir;
25813
25814 if(action!=rafting)
25815 stepforward(diagonalMovement?11:12, false);
25816
25817 break;
25818
25819 case dSHUTTER:
25820 case d1WAYSHUTTER:
25821 dir = scrolldir;
25822
25823 if(action!=rafting)
25824 stepforward(diagonalMovement?21:24, false);
25825
25826 putdoor(scrollbuf,0,scrolldir^1,tmpscr->door[scrolldir^1]);
25827 opendoors=-4;
25828 sfx(WAV_DOOR);
25829 break;
25830
25831 default:
25832 dir = scrolldir;
25833
25834 if(action!=rafting)
25835 stepforward(diagonalMovement?21:24, false);
25836 }
25837 }
25838
25839
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(action == scrolling)
25840 {
25841 action=none; FFCore.setHeroAction(none);
25842 }
25843
25844
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if(action != attacking && action != sideswimattacking)
25845 {
25846 3 charging = 0;
25847 3 tapping = false;
25848 3 }
25849
25850 3 map_bkgsfx(true);
25851
25852
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(newscr->flags2&fSECRET)
25853 {
25854 sfx(newscr->secretsfx);
25855 }
25856
25857 3 playLevelMusic();
25858
25859 3 newscr_clk = frame;
25860 3 activated_timed_warp=false;
25861 3 loadside = scrolldir^1;
25862 3 FFCore.init_combo_doscript();
25863 3 eventlog_mapflags();
25864 3 decorations.animate(); //continue to animate tall grass during scrolling
25865
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(get_bit(quest_rules,qr_FIXSCRIPTSDURINGSCROLLING))
25866 {
25867 //script_drawing_commands.Clear();
25868 ZScriptVersion::RunScrollingScript(scrolldir, cx, sx, sy, end_frames, false); //Prewaitdraw
25869 //ZScriptVersion::RunScrollingScript(scrolldir, cx, sx, sy, end_frames, true); //Waitdraw
25870 }
25871 3 }
25872
25873
25874
25875 // How much to reduce Hero's damage, taking into account various rings.
25876 int32_t HeroClass::ringpower(int32_t dmg, bool noPeril, bool noRing)
25877 {
25878 if(dmg < 0) return dmg; //Don't reduce healing
25879 if ( get_bit(quest_rules,qr_BROKEN_RING_POWER) )
25880 {
25881 int32_t divisor = 1;
25882 float percentage = 1;
25883 int32_t itemid = current_item_id(itype_ring);
25884 bool usering = false;
25885
25886 if(itemid>-1 && !noRing) // current_item_id checks magic cost for rings
25887 {
25888 usering = true;
25889 paymagiccost(itemid);
25890 if(itemsbuf[itemid].flags & ITEM_FLAG2)//"Divisor is Percentage Multiplier" flag
25891 {
25892 percentage *= itemsbuf[itemid].power/100.0;
25893 }
25894 else
25895 {
25896 divisor *= itemsbuf[itemid].power;
25897 }
25898 }
25899
25900 /* Now for the Peril Ring */
25901 itemid = current_item_id(itype_perilring);
25902
25903 if(itemid>-1 && !noPeril && game->get_life()<=itemsbuf[itemid].misc1*game->get_hp_per_heart() && checkmagiccost(itemid) && checkbunny(itemid))
25904 {
25905 usering = true;
25906 paymagiccost(itemid);
25907 if(itemsbuf[itemid].flags & ITEM_FLAG2)//"Divisor is Percentage Multiplier" flag
25908 {
25909 percentage *= itemsbuf[itemid].power/100.0;
25910 }
25911 else
25912 {
25913 divisor *= itemsbuf[itemid].power;
25914 }
25915 }
25916
25917 // Ring divisor of 0 = no damage. -L
25918 if(usering && (divisor==0 || percentage==0)) //Change dto allow negative power rings. -Z
25919 return 0;
25920
25921 if( percentage < 0 ) percentage = (percentage * -1) + 1; //Negative percentage = that percent MORE damage -V
25922
25923 if ( divisor < 0 ) return dmg * percentage * (divisor*-1);
25924 return dmg*percentage/( divisor != 0 ? divisor : 1 ); //zc_max(divisor, 1); // well, better safe...
25925
25926 }
25927 else
25928 {
25929 double divisor = 1;
25930 double percentage = 1;
25931 int32_t itemid = current_item_id(itype_ring);
25932 bool usering = false;
25933
25934 if(itemid>-1 && !noRing) // current_item_id checks magic cost for rings
25935 {
25936 usering = true;
25937 paymagiccost(itemid);
25938 if(itemsbuf[itemid].flags & ITEM_FLAG2)//"Divisor is Percentage Multiplier" flag
25939 {
25940 double perc = itemsbuf[itemid].power/100.0;
25941 if(perc < 0) perc = -perc + 1; //Negative percentage = that percent MORE damage -V
25942 percentage *= perc;
25943 }
25944 else
25945 {
25946 if(itemsbuf[itemid].power < 0)
25947 divisor /= -(itemsbuf[itemid].power);
25948 else divisor *= itemsbuf[itemid].power;
25949 }
25950 }
25951
25952 /* Now for the Peril Ring */
25953 itemid = current_item_id(itype_perilring);
25954
25955 if(itemid>-1 && !noPeril && game->get_life()<=itemsbuf[itemid].misc1*game->get_hp_per_heart() && checkmagiccost(itemid) && checkbunny(itemid))
25956 {
25957 usering = true;
25958 paymagiccost(itemid);
25959 if(itemsbuf[itemid].flags & ITEM_FLAG2)//"Divisor is Percentage Multiplier" flag
25960 {
25961 double perc = itemsbuf[itemid].power/100.0;
25962 if(perc < 0) perc = -perc + 1; //Negative percentage = that percent MORE damage -V
25963 percentage *= perc;
25964 }
25965 else
25966 {
25967 if(itemsbuf[itemid].power < 0)
25968 divisor /= -(itemsbuf[itemid].power);
25969 else divisor *= itemsbuf[itemid].power;
25970 }
25971 }
25972
25973 // Ring divisor of 0 = no damage. -L
25974 if(usering && (divisor==0 || percentage==0)) //Change dto allow negative power rings. -Z
25975 return 0;
25976
25977 //if ( divisor < 0 ) return dmg * percentage * (divisor*-1); //handle this further up now
25978 return dmg*percentage/( divisor != 0 ? divisor : 1 ); //zc_max(divisor, 1); // well, better safe...
25979 }
25980 }
25981
25982 // Should swinging the hammer make the 'pound' sound?
25983 // Or is Hero just hitting air?
25984 bool HeroClass::sideviewhammerpound()
25985 {
25986 int32_t wx=0,wy=0;
25987
25988 switch(dir)
25989 {
25990 case up:
25991 wx=-1;
25992 wy=-15;
25993
25994 if(isSideViewHero()) wy+=8;
25995
25996 break;
25997
25998 case down:
25999 wx=8;
26000 wy=28;
26001
26002 if(isSideViewHero()) wy-=8;
26003
26004 break;
26005
26006 case left:
26007 wx=-8;
26008 wy=14;
26009
26010 if(isSideViewHero()) wy+=8;
26011
26012 break;
26013
26014 case right:
26015 wx=21;
26016 wy=14;
26017
26018 if(isSideViewHero()) wy+=8;
26019
26020 break;
26021 }
26022
26023 if(!isSideViewHero())
26024 {
26025 return (COMBOTYPE(x+wx,y+wy)!=cSHALLOWWATER && !iswaterex(MAPCOMBO(x+wx,y+wy), currmap, currscr, -1, x+wx,y+wy));
26026 }
26027
26028 if(_walkflag(x+wx,y+wy,0,SWITCHBLOCK_STATE)) return true;
26029
26030 if(dir==left || dir==right)
26031 {
26032 wx+=16;
26033
26034 if(_walkflag(x+wx,y+wy,0,SWITCHBLOCK_STATE)) return true;
26035 }
26036
26037 return false;
26038 }
26039
26040 /************************************/
26041 /******** More Items Code *********/
26042 /************************************/
26043
26044 // The following are only used for Hero damage. Damage is in quarter hearts.
26045 int32_t enemy_dp(int32_t index)
26046 {
26047 return (((enemy*)guys.spr(index))->dp)*(game->get_ene_dmgmult());
26048 }
26049
26050 int32_t ewpn_dp(int32_t index)
26051 {
26052 return (((weapon*)Ewpns.spr(index))->power)*(game->get_ene_dmgmult());
26053 }
26054
26055 int32_t lwpn_dp(int32_t index)
26056 {
26057 return (((weapon*)Lwpns.spr(index))->power)*(game->get_ene_dmgmult());
26058 }
26059
26060 2473 bool checkbunny(int32_t itemid)
26061 {
26062
1/4
✓ Branch 0 taken 2473 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2473 return !Hero.BunnyClock() || (itemid > 0 && itemsbuf[itemid].flags&ITEM_BUNNY_ENABLED);
26063 }
26064
26065 5174 bool usesSwordJinx(int32_t itemid)
26066 {
26067 5174 itemdata const& it = itemsbuf[itemid];
26068 5174 bool ret = (it.family==itype_sword);
26069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5174 times.
5174 if(it.flags & ITEM_FLIP_JINX) return !ret;
26070 5174 return ret;
26071 5174 }
26072 5174 bool checkitem_jinx(int32_t itemid)
26073 {
26074 5174 itemdata const& it = itemsbuf[itemid];
26075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5174 times.
5174 if(it.flags & ITEM_JINX_IMMUNE) return true;
26076
2/2
✓ Branch 0 taken 1336 times.
✓ Branch 1 taken 3838 times.
5174 if(usesSwordJinx(itemid)) return HeroSwordClk() == 0;
26077 3838 return HeroItemClk() == 0;
26078 5174 }
26079
26080 1084 int32_t Bweapon(int32_t pos)
26081 {
26082
3/4
✓ Branch 0 taken 1084 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
✓ Branch 3 taken 1003 times.
1084 if(pos < 0 || current_subscreen_active == NULL)
26083 {
26084 81 return 0;
26085 }
26086
26087 1003 int32_t p=-1;
26088
26089
4/4
✓ Branch 0 taken 239 times.
✓ Branch 1 taken 31527 times.
✓ Branch 2 taken 239 times.
✓ Branch 3 taken 31527 times.
31766 for(int32_t i=0; current_subscreen_active->objects[i].type!=ssoNULL && i < MAXSUBSCREENITEMS; ++i)
26090 {
26091
4/4
✓ Branch 0 taken 22225 times.
✓ Branch 1 taken 9302 times.
✓ Branch 2 taken 21461 times.
✓ Branch 3 taken 764 times.
31527 if(current_subscreen_active->objects[i].type==ssoCURRENTITEM && current_subscreen_active->objects[i].d3==pos)
26092 {
26093 764 p=i;
26094 764 break;
26095 }
26096 30763 }
26097
26098
2/2
✓ Branch 0 taken 764 times.
✓ Branch 1 taken 239 times.
1003 if(p==-1)
26099 {
26100 239 return 0;
26101 }
26102
26103 764 int32_t actualItem = current_subscreen_active->objects[p].d8;
26104 //int32_t familyCheck = actualItem ? itemsbuf[actualItem].family : current_subscreen_active->objects[p].d1
26105 764 int32_t family = -1;
26106 764 bool bow = false;
26107
26108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 764 times.
764 if(actualItem)
26109 {
26110 bool select = false;
26111
26112 switch(itemsbuf[actualItem-1].family)
26113 {
26114 case itype_bomb:
26115 if((game->get_bombs() ||
26116 // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen.
26117 (actualItem-1>-1 && itemsbuf[actualItem-1].misc1==0 && findWeaponWithParent(actualItem-1, wLitBomb))) ||
26118 current_item_power(itype_bombbag))
26119 {
26120 select=true;
26121 }
26122
26123 break;
26124
26125 case itype_bowandarrow:
26126 case itype_arrow:
26127 if(actualItem-1>-1 && current_item_id(itype_bow)>-1)
26128 {
26129 //bow=(current_subscreen_active->objects[p].d1==itype_bowandarrow);
26130 select=true;
26131 }
26132
26133 break;
26134
26135 case itype_letterpotion:
26136 /*if(current_item_id(itype_potion)>-1)
26137 {
26138 select=true;
26139 }
26140 else if(current_item_id(itype_letter)>-1)
26141 {
26142 select=true;
26143 }*/
26144 break;
26145
26146 case itype_sbomb:
26147 {
26148 int32_t bombbagid = current_item_id(itype_bombbag);
26149
26150 if((game->get_sbombs() ||
26151 // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen.
26152 (actualItem-1>-1 && itemsbuf[actualItem-1].misc1==0 && findWeaponWithParent(actualItem-1, wLitSBomb))) ||
26153 (current_item_power(itype_bombbag) && bombbagid>-1 && (itemsbuf[bombbagid].flags & ITEM_FLAG1)))
26154 {
26155 select=true;
26156 }
26157
26158 break;
26159 }
26160
26161 case itype_sword:
26162 {
26163 if(!get_bit(quest_rules,qr_SELECTAWPN))
26164 break;
26165
26166 select=true;
26167 }
26168 break;
26169
26170 default:
26171 select=true;
26172 }
26173
26174 if(!item_disabled(actualItem-1) && game->get_item(actualItem-1) && select)
26175 {
26176 directItem = actualItem-1;
26177
26178 if(directItem>-1 && itemsbuf[directItem].family == itype_arrow) bow=true;
26179
26180 return actualItem-1+(bow?0xF000:0);
26181 }
26182 else return 0;
26183 }
26184
26185 764 directItem = -1;
26186
26187
5/6
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 502 times.
✓ Branch 3 taken 75 times.
✓ Branch 4 taken 75 times.
✗ Branch 5 not taken.
764 switch(current_subscreen_active->objects[p].d1)
26188 {
26189 case itype_bomb:
26190 {
26191 90 int32_t bombid = current_item_id(itype_bomb);
26192
26193
3/4
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
168 if((game->get_bombs() ||
26194 // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen.
26195
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
78 (bombid>-1 && itemsbuf[bombid].misc1==0 && Lwpns.idCount(wLitBomb)>0)) ||
26196 78 current_item_power(itype_bombbag))
26197 {
26198 12 family=itype_bomb;
26199 12 }
26200
26201 90 break;
26202 }
26203
26204 case itype_bowandarrow:
26205 case itype_arrow:
26206
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
75 if(current_item_id(itype_bow)>-1 && current_item_id(itype_arrow)>-1)
26207 {
26208 bow=(current_subscreen_active->objects[p].d1==itype_bowandarrow);
26209 family=itype_arrow;
26210 }
26211
26212 75 break;
26213
26214 case itype_letterpotion:
26215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if(current_item_id(itype_potion)>-1)
26216 {
26217 family=itype_potion;
26218 }
26219
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 else if(current_item_id(itype_letter)>-1)
26220 {
26221 family=itype_letter;
26222 }
26223
26224 75 break;
26225
26226 case itype_sbomb:
26227 {
26228 22 int32_t bombbagid = current_item_id(itype_bombbag);
26229 22 int32_t sbombid = current_item_id(itype_sbomb);
26230
26231
1/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
22 if((game->get_sbombs() ||
26232 // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen.
26233
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
22 (sbombid>-1 && itemsbuf[sbombid].misc1==0 && Lwpns.idCount(wLitSBomb)>0)) ||
26234
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
22 (current_item_power(itype_bombbag) && bombbagid>-1 && (itemsbuf[bombbagid].flags & ITEM_FLAG1)))
26235 {
26236 family=itype_sbomb;
26237 }
26238
26239 22 break;
26240 }
26241
26242 case itype_sword:
26243 {
26244 if(!get_bit(quest_rules,qr_SELECTAWPN))
26245 break;
26246
26247 family=itype_sword;
26248 }
26249 break;
26250
26251 default:
26252 502 family=current_subscreen_active->objects[p].d1;
26253 502 }
26254
26255
2/2
✓ Branch 0 taken 514 times.
✓ Branch 1 taken 250 times.
764 if(family==-1)
26256 250 return 0;
26257
26258
2/2
✓ Branch 0 taken 126264 times.
✓ Branch 1 taken 488 times.
126752 for(int32_t j=0; j<MAXITEMS; j++)
26259 {
26260 // Find the item that matches this subscreen object.
26261
5/6
✓ Branch 0 taken 792 times.
✓ Branch 1 taken 125472 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 766 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 26 times.
126264 if(itemsbuf[j].family==family && j == current_item_id(family,false) && !item_disabled(j))
26262 {
26263 26 return j+(bow?0xF000:0);
26264 }
26265 126238 }
26266
26267 488 return 0;
26268 1084 }
26269
26270 int32_t BWeapon_to_Pos(int32_t bweapon)
26271 {
26272 for (int32_t i = 0; i < MAXSUBSCREENITEMS; ++i)
26273 {
26274 if (Bweapon(i) == bweapon)
26275 {
26276 return i;
26277 }
26278 }
26279 return -1;
26280 }
26281
26282 void stopCaneOfByrna()
26283 {
26284 for(int32_t i=0; i<Lwpns.Count(); i++)
26285 {
26286 weapon *w = ((weapon*)Lwpns.spr(i));
26287 if(w->id==wCByrna)
26288 w->dead=1;
26289 }
26290 }
26291
26292 /* Crashes if used by ffscript.cpp, in case LINKITEMD
26293 void stopCaneOfByrna()
26294 {
26295 byte prnt_cane = -1;
26296 weapon *ew = (weapon*)(Lwpns.spr(Lwpns.idFirst(wCByrna)));
26297 prnt_cane = ew->parentitem;
26298 for(int32_t i=0; i<Lwpns.Count(); i++)
26299 {
26300 weapon *w = ((weapon*)Lwpns.spr(i));
26301
26302 if(w->id==wCByrna)
26303 {
26304 w->dead=1;
26305 }
26306 }
26307 if ( prnt_cane > -1 )
26308 {
26309 stop_sfx(itemsbuf[prnt_cane].usesound);
26310 }
26311 }
26312 */
26313 //Check if there are no beams, kill sfx, and reset last_cane_of_byrna_item_id
26314 1888 void HeroClass::cleanupByrna()
26315 {
26316
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if ( last_cane_of_byrna_item_id > -1 )
26317 {
26318 //al_trace("Last cane id is: %d\n", last_cane_of_byrna_item_id);
26319 if ( !(Lwpns.idCount(wCByrna)) )
26320 {
26321 stop_sfx(itemsbuf[last_cane_of_byrna_item_id].usesound);
26322 last_cane_of_byrna_item_id = -1;
26323 }
26324 }
26325 1888 }
26326
26327 // Used to find out if an item family is attached to one of the buttons currently pressed.
26328 238 bool isWpnPressed(int32_t itype)
26329 {
26330 //0xFFF for subscreen overrides
26331 //Will crash on win10 without it! -Z
26332
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
238 if((itype==getItemFamily(itemsbuf,Bwpn&0xFFF)) && DrunkcBbtn()) return true;
26333
3/4
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 114 times.
✓ Branch 3 taken 124 times.
238 if((itype==getItemFamily(itemsbuf,Awpn&0xFFF)) && DrunkcAbtn()) return true;
26334
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
114 if((itype==getItemFamily(itemsbuf,Xwpn&0xFFF)) && DrunkcEx1btn()) return true;
26335
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
114 if((itype==getItemFamily(itemsbuf,Ywpn&0xFFF)) && DrunkcEx2btn()) return true;
26336 114 return false;
26337 238 }
26338
26339 1523 int32_t getWpnPressed(int32_t itype)
26340 {
26341
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1523 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1523 if((itype==getItemFamily(itemsbuf,Bwpn&0xFFF)) && DrunkcBbtn()) return Bwpn;
26342
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1523 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1523 if((itype==getItemFamily(itemsbuf,Awpn&0xFFF)) && DrunkcAbtn()) return Awpn;
26343
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1523 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1523 if((itype==getItemFamily(itemsbuf,Xwpn&0xFFF)) && DrunkcEx1btn()) return Xwpn;
26344
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1523 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1523 if((itype==getItemFamily(itemsbuf,Ywpn&0xFFF)) && DrunkcEx2btn()) return Ywpn;
26345
26346 1523 return -1;
26347 1523 }
26348
26349 bool isItmPressed(int32_t itmid)
26350 {
26351 if(itmid==(Bwpn&0xFFF) && DrunkcBbtn()) return true;
26352 if(itmid==(Awpn&0xFFF) && DrunkcAbtn()) return true;
26353 if(itmid==(Xwpn&0xFFF) && DrunkcEx1btn()) return true;
26354 if(itmid==(Ywpn&0xFFF) && DrunkcEx2btn()) return true;
26355 return false;
26356 }
26357
26358 void selectNextAWpn(int32_t type)
26359 {
26360 if(!get_bit(quest_rules,qr_SELECTAWPN))
26361 return;
26362
26363 int32_t ret = selectWpn_new(type, game->awpn, game->bwpn, get_bit(quest_rules,qr_SET_XBUTTON_ITEMS) ? game->xwpn : -1, get_bit(quest_rules,qr_SET_YBUTTON_ITEMS) ? game->ywpn : -1);
26364 Awpn = Bweapon(ret);
26365 directItemA = directItem;
26366 game->awpn = ret;
26367 }
26368
26369 void selectNextBWpn(int32_t type)
26370 {
26371 int32_t ret = selectWpn_new(type, game->bwpn, game->awpn, get_bit(quest_rules,qr_SET_XBUTTON_ITEMS) ? game->xwpn : -1, get_bit(quest_rules,qr_SET_YBUTTON_ITEMS) ? game->ywpn : -1);
26372 Bwpn = Bweapon(ret);
26373 directItemB = directItem;
26374 game->bwpn = ret;
26375 }
26376
26377 void selectNextXWpn(int32_t type)
26378 {
26379 if(!get_bit(quest_rules,qr_SET_XBUTTON_ITEMS)) return;
26380 int32_t ret = selectWpn_new(type, game->xwpn, game->awpn, game->bwpn, get_bit(quest_rules,qr_SET_YBUTTON_ITEMS) ? game->ywpn : -1);
26381 Xwpn = Bweapon(ret);
26382 directItemX = directItem;
26383 game->xwpn = ret;
26384 }
26385
26386 void selectNextYWpn(int32_t type)
26387 {
26388 if(!get_bit(quest_rules,qr_SET_YBUTTON_ITEMS)) return;
26389 int32_t ret = selectWpn_new(type, game->ywpn, game->awpn, game->bwpn, get_bit(quest_rules,qr_SET_XBUTTON_ITEMS) ? game->xwpn : -1);
26390 Ywpn = Bweapon(ret);
26391 directItemY = directItem;
26392 game->ywpn = ret;
26393 }
26394
26395 114 void verifyAWpn()
26396 {
26397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 if ( (game->forced_awpn != -1) )
26398 {
26399 return;
26400 }
26401
1/2
✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
114 if(!get_bit(quest_rules,qr_SELECTAWPN))
26402 {
26403 114 Awpn = selectSword();
26404 114 game->awpn = 0xFF;
26405 114 }
26406 else
26407 {
26408 game->awpn = selectWpn_new(SEL_VERIFY_RIGHT, game->awpn, game->bwpn, game->xwpn, game->ywpn);
26409 Awpn = Bweapon(game->awpn);
26410 directItemA = directItem;
26411 }
26412 114 }
26413
26414 111 void verifyBWpn()
26415 {
26416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
111 if ( (game->forced_bwpn != -1) )
26417 {
26418 return;
26419 }
26420 111 game->bwpn = selectWpn_new(SEL_VERIFY_RIGHT, game->bwpn, game->awpn, game->xwpn, game->ywpn);
26421 111 Bwpn = Bweapon(game->bwpn);
26422 111 directItemB = directItem;
26423 111 }
26424
26425 111 void verifyXWpn()
26426 {
26427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
111 if ( (game->forced_xwpn != -1) )
26428 {
26429 return;
26430 }
26431
1/2
✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
111 if(get_bit(quest_rules,qr_SET_XBUTTON_ITEMS))
26432 game->xwpn = selectWpn_new(SEL_VERIFY_RIGHT, game->xwpn, game->awpn, game->bwpn, game->ywpn);
26433 111 else game->xwpn = -1;
26434 111 Xwpn = Bweapon(game->xwpn);
26435 111 directItemX = directItem;
26436 111 }
26437
26438 111 void verifyYWpn()
26439 {
26440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
111 if ( (game->forced_ywpn != -1) )
26441 {
26442 return;
26443 }
26444
1/2
✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
111 if(get_bit(quest_rules,qr_SET_YBUTTON_ITEMS))
26445 game->ywpn = selectWpn_new(SEL_VERIFY_RIGHT, game->ywpn, game->awpn, game->xwpn, game->bwpn);
26446 111 else game->ywpn = -1;
26447 111 Ywpn = Bweapon(game->ywpn);
26448 111 directItemY = directItem;
26449 111 }
26450
26451 111 void verifyBothWeapons()
26452 {
26453 111 verifyAWpn();
26454 111 verifyBWpn();
26455 111 verifyXWpn();
26456 111 verifyYWpn();
26457 111 }
26458
26459 114 int32_t selectWpn_new(int32_t type, int32_t startpos, int32_t forbiddenpos, int32_t fp2, int32_t fp3)
26460 {
26461 //what will be returned when all else fails.
26462 //don't return the forbiddenpos... no matter what -DD
26463
26464 114 int32_t failpos(0);
26465
26466
5/6
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
114 if(startpos == forbiddenpos || startpos == fp2 || startpos == fp3)
26467 97 failpos = 0xFF;
26468 17 else failpos = startpos;
26469
26470 // verify startpos
26471
3/4
✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 89 times.
✓ Branch 3 taken 25 times.
114 if(startpos < 0 || startpos >= 0xFF)
26472 89 startpos = 0;
26473
26474
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 27 times.
114 if(current_subscreen_active == NULL)
26475 27 return failpos;
26476
26477
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
87 if(type==SEL_VERIFY_RIGHT || type==SEL_VERIFY_LEFT)
26478 {
26479 87 int32_t wpn = Bweapon(startpos);
26480
26481
5/8
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
87 if(wpn != 0 && startpos != forbiddenpos && startpos != fp2 && startpos != fp3)
26482 {
26483 11 return startpos;
26484 }
26485 76 }
26486
26487 76 int32_t p=-1;
26488 76 int32_t curpos = startpos;
26489 76 int32_t firstValidPos=-1;
26490
26491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1718 times.
1718 for(int32_t i=0; current_subscreen_active->objects[i].type!=ssoNULL; ++i)
26492 {
26493
2/2
✓ Branch 0 taken 699 times.
✓ Branch 1 taken 1019 times.
1718 if(current_subscreen_active->objects[i].type==ssoCURRENTITEM)
26494 {
26495
4/4
✓ Branch 0 taken 1016 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 940 times.
✓ Branch 3 taken 76 times.
1019 if(firstValidPos==-1 && current_subscreen_active->objects[i].d3>=0)
26496 {
26497 76 firstValidPos=i;
26498 76 }
26499
26500
2/2
✓ Branch 0 taken 943 times.
✓ Branch 1 taken 76 times.
1019 if(current_subscreen_active->objects[i].d3==curpos)
26501 {
26502 76 p=i;
26503 76 break;
26504 }
26505 943 }
26506 1642 }
26507
26508
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 if(p == -1)
26509 {
26510 //can't find the current position
26511 // Switch to a valid weapon if there is one; otherwise,
26512 // the selector can simply disappear
26513 if(firstValidPos>=0)
26514 {
26515 return current_subscreen_active->objects[firstValidPos].d3;
26516 }
26517 //FAILURE
26518 else
26519 {
26520 return failpos;
26521 }
26522 }
26523
26524 //remember we've been here
26525 76 set<int32_t> oldPositions;
26526
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 oldPositions.insert(curpos);
26527
26528 //1. Perform any shifts required by the above
26529 //2. If that's not possible, go to position 1 and reset the b weapon.
26530 //2a. -if we arrive at a position we've already visited, give up and stay there
26531 //3. Get the weapon at the new slot
26532 //4. If it's not possible, go to step 1.
26533
26534 735 for(;;)
26535 {
26536 //shift
26537
1/5
✗ Branch 0 not taken.
✓ Branch 1 taken 735 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
735 switch(type)
26538 {
26539 case SEL_LEFT:
26540 case SEL_VERIFY_LEFT:
26541 curpos = current_subscreen_active->objects[p].d6;
26542 break;
26543
26544 case SEL_RIGHT:
26545 case SEL_VERIFY_RIGHT:
26546 735 curpos = current_subscreen_active->objects[p].d7;
26547 735 break;
26548
26549 case SEL_DOWN:
26550 curpos = current_subscreen_active->objects[p].d5;
26551 break;
26552
26553 case SEL_UP:
26554 curpos = current_subscreen_active->objects[p].d4;
26555 break;
26556 }
26557
26558 //find our new position
26559 735 p = -1;
26560
26561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22237 times.
22237 for(int32_t i=0; current_subscreen_active->objects[i].type!=ssoNULL; ++i)
26562 {
26563
2/2
✓ Branch 0 taken 6660 times.
✓ Branch 1 taken 15577 times.
22237 if(current_subscreen_active->objects[i].type==ssoCURRENTITEM)
26564 {
26565
2/2
✓ Branch 0 taken 14842 times.
✓ Branch 1 taken 735 times.
15577 if(current_subscreen_active->objects[i].d3==curpos)
26566 {
26567 735 p=i;
26568 735 break;
26569 }
26570 14842 }
26571 21502 }
26572
26573
1/2
✓ Branch 0 taken 735 times.
✗ Branch 1 not taken.
735 if(p == -1)
26574 {
26575 //can't find the current position
26576 //FAILURE
26577 return failpos;
26578 }
26579
26580 //if we've already been here, give up
26581
4/6
✓ Branch 0 taken 735 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 735 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 661 times.
✓ Branch 5 taken 74 times.
735 if(oldPositions.find(curpos) != oldPositions.end())
26582 {
26583 74 return failpos;
26584 }
26585
26586 //else, remember we've been here
26587
1/2
✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
661 oldPositions.insert(curpos);
26588
26589 //see if this weapon is acceptable
26590
6/10
✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 659 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
661 if(Bweapon(curpos) != 0 && curpos != forbiddenpos && curpos != fp2 && curpos != fp3)
26591 2 return curpos;
26592
26593 //keep going otherwise
26594 }
26595 114 }
26596
26597 // Select the sword for the A button if the 'select A button weapon' quest rule isn't set.
26598 117 int32_t selectSword()
26599 {
26600 117 auto ret = current_item_id(itype_sword);
26601
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 24 times.
117 if(ret == -1) return 0;
26602 24 return ret;
26603 117 }
26604
26605 // Adding code here for allowing hardcoding a button to a specific itemclass.
26606 int32_t selectItemclass(int32_t itemclass)
26607 {
26608 int32_t ret = current_item_id(itemclass);
26609
26610 if(ret == -1)
26611 ret = 0;
26612
26613 return ret;
26614 }
26615
26616 // Used for the 'Pickup Hearts' item pickup condition.
26617 1 bool canget(int32_t id)
26618 {
26619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 return id>=0 && (game->get_maxlife()>=(itemsbuf[id].pickup_hearts*game->get_hp_per_heart()));
26620 }
26621
26622 void dospecialmoney(int32_t index)
26623 {
26624 int32_t tmp=currscr>=128?1:0;
26625 int32_t priceindex = ((item*)items.spr(index))->PriceIndex;
26626
26627 switch(tmpscr[tmp].room)
26628 {
26629 case rINFO: // pay for info
26630 if(prices[priceindex]!=100000 ) // 100000 is a placeholder price for free items
26631 {
26632
26633
26634 if(!current_item_power(itype_wallet))
26635 {
26636 if (game->get_spendable_rupies() < abs(prices[priceindex]))
26637 return;
26638 int32_t tmpprice = -abs(prices[priceindex]);
26639 int32_t total = game->get_drupy()-tmpprice;
26640 total = vbound(total, 0, game->get_maxcounter(1)); //Never overflow! Overflow here causes subscreen bugs! -Z
26641 game->set_drupy(game->get_drupy()-total);
26642 //game->change_drupy(-abs(prices[priceindex]));
26643 }
26644 if ( current_item_power(itype_wallet)>0 )
26645 {
26646 game->change_drupy(0);
26647 }
26648 }
26649 rectfill(msg_bg_display_buf, 0, 0, msg_bg_display_buf->w, 80, 0);
26650 rectfill(msg_txt_display_buf, 0, 0, msg_txt_display_buf->w, 80, 0);
26651 donewmsg(QMisc.info[tmpscr[tmp].catchall].str[priceindex]);
26652 clear_bitmap(pricesdisplaybuf);
26653 set_clip_state(pricesdisplaybuf, 1);
26654 items.del(0);
26655
26656 for(int32_t i=0; i<items.Count(); i++)
26657 ((item*)items.spr(i))->pickup=ipDUMMY;
26658
26659 // Prevent the prices from being displayed anymore
26660 for(int32_t i=0; i<3; i++)
26661 {
26662 prices[i] = 0;
26663 }
26664
26665 break;
26666
26667 case rMONEY: // secret money
26668 {
26669 ((item*)items.spr(0))->pickup = ipDUMMY;
26670
26671 prices[0] = tmpscr[tmp].catchall;
26672 if (!current_item_power(itype_wallet))
26673 game->change_drupy(prices[0]);
26674 //game->set_drupy(game->get_drupy()+price); may be needed everywhere
26675
26676 putprices(false);
26677 setmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM);
26678 break;
26679 }
26680
26681 case rGAMBLE: // gamble
26682 {
26683 if(game->get_spendable_rupies()<10 && !current_item_power(itype_wallet)) return; //Why 10?
26684
26685 unsigned si=(zc_oldrand()%24)*3;
26686
26687 for(int32_t i=0; i<3; i++)
26688 prices[i]=gambledat[si++];
26689
26690 game->set_drupy(game->get_drupy()+prices[priceindex]);
26691 putprices(true);
26692
26693 for(int32_t i=1; i<4; i++)
26694 ((item*)items.spr(i))->pickup=ipDUMMY;
26695 }
26696 break;
26697
26698 case rBOMBS:
26699 {
26700 if(game->get_spendable_rupies()<tmpscr[tmp].catchall && !current_item_power(itype_wallet))
26701 return;
26702
26703 int32_t price = -tmpscr[tmp].catchall;
26704 int32_t wmedal = current_item_id(itype_wealthmedal);
26705 if(wmedal >= 0)
26706 {
26707 if(itemsbuf[wmedal].flags & ITEM_FLAG1)
26708 price*=(itemsbuf[wmedal].misc1/100.0);
26709 else
26710 price+=itemsbuf[wmedal].misc1;
26711 }
26712
26713 int32_t total = game->get_drupy()-price;
26714 total = vbound(total, 0, game->get_maxcounter(1)); //Never overflow! Overflow here causes subscreen bugs! -Z
26715 game->set_drupy(game->get_drupy()-total);
26716 //game->set_drupy(game->get_drupy()+price);
26717 setmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM);
26718 game->change_maxbombs(4);
26719 game->set_bombs(game->get_maxbombs());
26720 {
26721 int32_t div = zinit.bomb_ratio;
26722
26723 if(div > 0)
26724 game->change_maxcounter(4/div, 6);
26725 }
26726
26727 //also give Hero an actual Bomb item
26728 for(int32_t i=0; i<MAXITEMS; i++)
26729 {
26730 if(itemsbuf[i].family == itype_bomb && itemsbuf[i].fam_type == 1)
26731 getitem(i, true, true);
26732 }
26733
26734 ((item*)items.spr(index))->pickup=ipDUMMY+ipFADE;
26735 fadeclk=66;
26736 dismissmsg();
26737 clear_bitmap(pricesdisplaybuf);
26738 set_clip_state(pricesdisplaybuf, 1);
26739 // putscr(scrollbuf,0,0,tmpscr);
26740 verifyBothWeapons();
26741 break;
26742 }
26743
26744 case rARROWS:
26745 {
26746 if(game->get_spendable_rupies()<tmpscr[tmp].catchall && !current_item_power(itype_wallet))
26747 return;
26748
26749 int32_t price = -tmpscr[tmp].catchall;
26750 int32_t wmedal = current_item_id(itype_wealthmedal);
26751 if(wmedal >= 0)
26752 {
26753 if(itemsbuf[wmedal].flags & ITEM_FLAG1)
26754 price*=(itemsbuf[wmedal].misc1/100.0);
26755 else
26756 price+=itemsbuf[wmedal].misc1;
26757 }
26758
26759 int32_t total = game->get_drupy()-price;
26760 total = vbound(total, 0, game->get_maxcounter(1)); //Never overflow! Overflow here causes subscreen bugs! -Z
26761 game->set_drupy(game->get_drupy()-total);
26762
26763 //game->set_drupy(game->get_drupy()+price);
26764 setmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM);
26765 game->change_maxarrows(10);
26766 game->set_arrows(game->get_maxarrows());
26767 ((item*)items.spr(index))->pickup=ipDUMMY+ipFADE;
26768 fadeclk=66;
26769 dismissmsg();
26770 clear_bitmap(pricesdisplaybuf);
26771 set_clip_state(pricesdisplaybuf, 1);
26772 // putscr(scrollbuf,0,0,tmpscr);
26773 verifyBothWeapons();
26774 break;
26775 }
26776
26777 case rSWINDLE:
26778 if(items.spr(index)->id==iRupy)
26779 {
26780 if(game->get_spendable_rupies()<tmpscr[tmp].catchall && !current_item_power(itype_wallet))
26781 return;
26782 int32_t tmpprice = -tmpscr[tmp].catchall;
26783 int32_t total = game->get_drupy()-tmpprice;
26784 total = vbound(total, 0, game->get_maxcounter(1)); //Never overflow! Overflow here causes subscreen bugs! -Z
26785 game->set_drupy(game->get_drupy()-total);
26786 }
26787 else
26788 {
26789 if(game->get_maxlife()<=game->get_hp_per_heart())
26790 return;
26791
26792 game->set_life(zc_max(game->get_life()-game->get_hp_per_heart(),0));
26793 game->set_maxlife(zc_max(game->get_maxlife()-game->get_hp_per_heart(),(game->get_hp_per_heart())));
26794 }
26795
26796 setmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM);
26797 ((item*)items.spr(0))->pickup=ipDUMMY+ipFADE;
26798 ((item*)items.spr(1))->pickup=ipDUMMY+ipFADE;
26799 fadeclk=66;
26800 dismissmsg();
26801 clear_bitmap(pricesdisplaybuf);
26802 set_clip_state(pricesdisplaybuf, 1);
26803 // putscr(scrollbuf,0,0,tmpscr);
26804 break;
26805 }
26806 }
26807
26808 19 void getitem(int32_t id, bool nosound, bool doRunPassive)
26809 {
26810
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if(id<0)
26811 {
26812 return;
26813 }
26814
26815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (replay_is_active())
26816
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 replay_step_comment(fmt::format("getitem {}", item_string[id]));
26817
26818
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 3 times.
19 if(get_bit(quest_rules,qr_SCC_ITEM_COMBINES_ITEMS))
26819 {
26820 3 int32_t nextitem = -1;
26821 3 do
26822 {
26823 3 nextitem = -1;
26824
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if((itemsbuf[id].flags & ITEM_COMBINE) && game->get_item(id))
26825 // Item upgrade routine.
26826 {
26827
26828 for(int32_t i=0; i<MAXITEMS; i++)
26829 {
26830 // Find the item which is as close to this item's fam_type as possible.
26831 if(itemsbuf[i].family==itemsbuf[id].family && itemsbuf[i].fam_type>itemsbuf[id].fam_type
26832 && (nextitem>-1 ? itemsbuf[i].fam_type<=itemsbuf[nextitem].fam_type : true))
26833 {
26834 nextitem = i;
26835 }
26836 }
26837
26838 if(nextitem>-1)
26839 {
26840 id = nextitem;
26841 if(!get_bit(quest_rules,qr_ITEMCOMBINE_CONTINUOUS))
26842 break; //no looping
26843 }
26844 }
26845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } while(nextitem > -1);
26846 3 }
26847
26848 19 itemdata const& idat = itemsbuf[id&0xFF];
26849 // if(idat.family!=0xFF) //1.92 compat... that already should be changed to 'itype_misc'? Blehg, hate this! -Em
26850 {
26851
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
19 if(idat.flags & ITEM_GAMEDATA && idat.family != itype_triforcepiece)
26852 {
26853 // Fix boomerang sounds.
26854 18 int32_t itemid = current_item_id(idat.family);
26855
26856
3/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
18 if(itemid>=0 && (idat.family == itype_brang || idat.family == itype_nayruslove
26857
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 || idat.family == itype_hookshot || idat.family == itype_switchhook || idat.family == itype_cbyrna)
26858 1 && sfx_allocated(itemsbuf[itemid].usesound)
26859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 && idat.usesound != itemsbuf[itemid].usesound)
26860 {
26861 stop_sfx(itemsbuf[itemid].usesound);
26862 cont_sfx(idat.usesound);
26863 }
26864
26865 18 int32_t curitm = current_item_id(idat.family);
26866
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
18 if(!get_bit(quest_rules,qr_KEEPOLD_APPLIES_RETROACTIVELY)
26867
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 || curitm < 0 || (itemsbuf[curitm].fam_type <= idat.fam_type)
26868 || (itemsbuf[curitm].flags & ITEM_KEEPOLD))
26869 {
26870 18 game->set_item(id,true);
26871 18 passiveitem_script(id, doRunPassive);
26872 18 }
26873
26874
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 5 times.
18 if(!(idat.flags & ITEM_KEEPOLD))
26875 {
26876
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
5 if(!get_bit(quest_rules,qr_BROKEN_KEEPOLD_FLAG) || current_item(idat.family)<idat.fam_type)
26877 {
26878 1 removeLowerLevelItemsOfFamily(game,itemsbuf,idat.family, idat.fam_type);
26879 1 }
26880 5 }
26881
26882 // NES consistency: replace all flying boomerangs with the current boomerang.
26883
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if(idat.family==itype_brang)
26884 for(int32_t i=0; i<Lwpns.Count(); i++)
26885 {
26886 weapon *w = ((weapon*)Lwpns.spr(i));
26887
26888 if(w->id==wBrang)
26889 {
26890 w->LOADGFX(idat.wpn);
26891 }
26892 }
26893 18 }
26894
26895
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8 times.
19 if(idat.count!=-1)
26896 {
26897
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if(idat.setmax)
26898 {
26899 // Bomb bags are a special case; they may be set not to increase super bombs
26900 if(idat.family==itype_bombbag && idat.count==2 && (idat.flags&16)==0)
26901 {
26902 int32_t max = game->get_maxbombs();
26903
26904 if(max<idat.max) max=idat.max;
26905
26906 game->set_maxbombs(zc_min(game->get_maxbombs()+idat.setmax,max), false);
26907 }
26908 else
26909 {
26910 int32_t max = game->get_maxcounter(idat.count);
26911
26912 if(max<idat.max) max=idat.max;
26913
26914 game->set_maxcounter(zc_min(game->get_maxcounter(idat.count)+idat.setmax,max), idat.count);
26915 }
26916 }
26917
26918 // Amount is an uint16_t, but the range is -9999 to 16383
26919 // -1 is actually 16385 ... -9999 is 26383, and 0x8000 means use the drain counter
26920
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if(idat.amount&0x3FFF)
26921 {
26922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(idat.amount&0x8000)
26923 game->set_dcounter(
26924 game->get_dcounter(idat.count)+((idat.amount&0x4000)?-(idat.amount&0x3FFF):idat.amount&0x3FFF), idat.count);
26925 else
26926 {
26927
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if(idat.amount>=16385 && game->get_counter(0)<=idat.amount-16384)
26928 game->set_counter(0, idat.count);
26929 else
26930 // This is too confusing to try and change...
26931
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
2 game->set_counter(zc_min(game->get_counter(idat.count)+((idat.amount&0x4000)?-(idat.amount&0x3FFF):idat.amount&0x3FFF),game->get_maxcounter(idat.count)), idat.count);
26932 }
26933 2 }
26934 8 }
26935 }
26936
26937
3/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 2 times.
19 if(idat.playsound&&!nosound)
26938 {
26939 2 sfx(idat.playsound);
26940 2 }
26941
26942 //add lower-level items
26943
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if(idat.flags&ITEM_GAINOLD)
26944 {
26945 for(int32_t i=idat.fam_type-1; i>0; i--)
26946 {
26947 int32_t potid = getItemID(itemsbuf, idat.family, i);
26948
26949 if(potid != -1)
26950 {
26951 game->set_item(potid, true);
26952 }
26953 }
26954 }
26955
26956
1/14
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
19 switch(idat.family)
26957 {
26958 case itype_itmbundle:
26959 {
26960 int ids[10] = {idat.misc1, idat.misc2, idat.misc3, idat.misc4, idat.misc5,
26961 idat.misc6, idat.misc7, idat.misc8, idat.misc9, idat.misc10};
26962 bool pscript = (idat.flags & ITEM_FLAG1);
26963 for(auto q = 0; q < 10; ++q)
26964 {
26965 if(unsigned(ids[q]) >= MAXITEMS) continue;
26966 if(pscript)
26967 collectitem_script(ids[q]);
26968 getitem(ids[q], true, true);
26969 }
26970 }
26971 break;
26972
26973 case itype_progressive_itm:
26974 {
26975 int32_t newid = get_progressive_item(idat);
26976 if(newid > -1)
26977 getitem(newid, nosound, true);
26978 }
26979 break;
26980
26981 case itype_bottlefill:
26982 {
26983 if(idat.misc1)
26984 {
26985 game->fillBottle(idat.misc1);
26986 }
26987 }
26988 break;
26989
26990 case itype_clock:
26991 {
26992 if(idat.flags & ITEM_FLAG1) //Active use, not passive
26993 break;
26994 if((idat.flags & ITEM_FLAG2) && clockclk) //"Can't activate while clock active"
26995 break;
26996 setClock(watch=true);
26997
26998 for(int32_t i=0; i<eMAXGUYS; i++)
26999 clock_zoras[i]=0;
27000
27001 clockclk=itemsbuf[id&0xFF].misc1;
27002 sfx(idat.usesound);
27003 }
27004 break;
27005
27006 case itype_lkey:
27007 if(game->lvlkeys[dlevel]<255) game->lvlkeys[dlevel]++;
27008 break;
27009
27010 case itype_ring:
27011 case itype_magicring:
27012 if((get_bit(quest_rules,qr_OVERWORLDTUNIC) != 0) || (currscr<128 || dlevel))
27013 {
27014 ringcolor(false);
27015 }
27016 break;
27017
27018 case itype_whispring:
27019 {
27020 if(idat.flags & ITEM_FLAG1)
27021 {
27022 if(HeroSwordClk()==-1) setSwordClk(150); // Let's not bother applying the divisor.
27023
27024 if(HeroItemClk()==-1) setItemClk(150); // Let's not bother applying the divisor.
27025 }
27026
27027 if(idat.power==0)
27028 {
27029 setSwordClk(0);
27030 setItemClk(0);
27031 }
27032
27033 break;
27034 }
27035
27036
27037 case itype_map:
27038 game->lvlitems[dlevel]|=liMAP;
27039 break;
27040
27041 case itype_compass:
27042 game->lvlitems[dlevel]|=liCOMPASS;
27043 break;
27044
27045 case itype_bosskey:
27046 game->lvlitems[dlevel]|=liBOSSKEY;
27047 break;
27048
27049 case itype_fairy:
27050
27051 game->set_life(zc_min(game->get_life()+(idat.flags&ITEM_FLAG1 ?(int32_t)(game->get_maxlife()*(idat.misc1/100.0)):((idat.misc1*game->get_hp_per_heart()))),game->get_maxlife()));
27052 game->set_magic(zc_min(game->get_magic()+(idat.flags&ITEM_FLAG2 ?(int32_t)(game->get_maxmagic()*(idat.misc2/100.0)):((idat.misc2*game->get_mp_per_block()))),game->get_maxmagic()));
27053 break;
27054
27055 case itype_heartpiece:
27056 game->change_HCpieces(1);
27057
27058 if(game->get_HCpieces()<game->get_hcp_per_hc())
27059 break;
27060
27061 game->set_HCpieces(0);
27062
27063 getitem(heart_container_id());
27064 break;
27065
27066 case itype_killem:
27067 {
27068 if(idat.flags & ITEM_FLAG1) //Active use, not passive
27069 break;
27070 kill_em_all();
27071 sfx(idat.usesound);
27072 }
27073 break;
27074 }
27075
27076 19 update_subscreens();
27077 19 load_Sitems(&QMisc);
27078 19 verifyBothWeapons();
27079 19 }
27080
27081 void takeitem(int32_t id)
27082 {
27083 game->set_item(id, false);
27084 itemdata const& idat = itemsbuf[id];
27085
27086 /* Lower the counters! */
27087 if(idat.count!=-1)
27088 {
27089 if(idat.setmax)
27090 {
27091 game->set_maxcounter(game->get_maxcounter(idat.count)-idat.setmax, idat.count);
27092 }
27093
27094 if(idat.amount&0x3FFF)
27095 {
27096 if(idat.amount&0x8000)
27097 game->set_dcounter(game->get_dcounter(idat.count)-((idat.amount&0x4000)?-(idat.amount&0x3FFF):idat.amount&0x3FFF), idat.count);
27098 else game->set_counter(game->get_counter(idat.count)-((idat.amount&0x4000)?-(idat.amount&0x3FFF):idat.amount&0x3FFF), idat.count);
27099 }
27100 }
27101
27102 switch(itemsbuf[id&0xFF].family)
27103 {
27104 // NES consistency: replace all flying boomerangs with the current boomerang.
27105 case itype_brang:
27106 if(current_item(itype_brang)) for(int32_t i=0; i<Lwpns.Count(); i++)
27107 {
27108 weapon *w = ((weapon*)Lwpns.spr(i));
27109
27110 if(w->id==wBrang)
27111 {
27112 w->LOADGFX(itemsbuf[current_item_id(itype_brang)].wpn);
27113 }
27114 }
27115
27116 break;
27117
27118 case itype_itmbundle:
27119 {
27120 int ids[10] = {idat.misc1, idat.misc2, idat.misc3, idat.misc4, idat.misc5,
27121 idat.misc6, idat.misc7, idat.misc8, idat.misc9, idat.misc10};
27122 for(auto q = 0; q < 10; ++q)
27123 {
27124 if(unsigned(ids[q]) >= MAXITEMS) continue;
27125 takeitem(ids[q]);
27126 }
27127 }
27128 break;
27129
27130 case itype_progressive_itm:
27131 {
27132 int32_t newid = get_progressive_item(idat, true);
27133 if(newid > -1)
27134 takeitem(newid);
27135 }
27136 break;
27137
27138 case itype_heartpiece:
27139 if(game->get_maxlife()>game->get_hp_per_heart())
27140 {
27141 if(game->get_HCpieces()==0)
27142 {
27143 game->set_HCpieces(game->get_hcp_per_hc());
27144 takeitem(iHeartC);
27145 }
27146
27147 game->change_HCpieces(-1);
27148 }
27149 break;
27150
27151 case itype_map:
27152 game->lvlitems[dlevel]&=~liMAP;
27153 break;
27154
27155 case itype_compass:
27156 game->lvlitems[dlevel]&=~liCOMPASS;
27157 break;
27158
27159 case itype_bosskey:
27160 game->lvlitems[dlevel]&=~liBOSSKEY;
27161 break;
27162
27163 case itype_lkey:
27164 if(game->lvlkeys[dlevel]) game->lvlkeys[dlevel]--;
27165 break;
27166
27167 case itype_ring:
27168 if((get_bit(quest_rules,qr_OVERWORLDTUNIC) != 0) || (currscr<128 || dlevel))
27169 {
27170 ringcolor(false);
27171 }
27172 break;
27173 }
27174 }
27175
27176 // Attempt to pick up an item. (-1 = check items touching Hero.)
27177 1888 void HeroClass::checkitems(int32_t index)
27178 {
27179 1888 int32_t tmp=currscr>=128?1:0;
27180
27181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(index==-1)
27182 {
27183
2/2
✓ Branch 0 taken 759 times.
✓ Branch 1 taken 1888 times.
2647 for(auto ind = items.Count()-1; ind >= 0; --ind)
27184 {
27185 759 item* itm = (item*)items.spr(ind);
27186
1/2
✓ Branch 0 taken 759 times.
✗ Branch 1 not taken.
759 if(itm->get_forcegrab())
27187 {
27188 checkitems(ind);
27189 }
27190 759 }
27191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(diagonalMovement)
27192 {
27193 index=items.hit(x,y+(bigHitbox?0:8)-fakez,z,6,6,1);
27194 }
27195 1888 else index=items.hit(x,y+(bigHitbox?0:8)-fakez,z,1,1,1);
27196 1888 }
27197
27198
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1886 times.
1888 if(index==-1)
27199 1886 return;
27200
27201 // if (tmpscr[tmp].room==rSHOP && boughtsomething==true)
27202 // return;
27203 2 item* ptr = (item*)items.spr(index);
27204 2 int32_t pickup = ptr->pickup;
27205 2 int8_t exstate = ptr->pickupexstate;
27206 2 int32_t PriceIndex = ptr->PriceIndex;
27207 2 int32_t id2 = ptr->id;
27208 2 int32_t holdid = ptr->id;
27209 2 int32_t pstr = ptr->pstring;
27210 2 int32_t pstr_flags = ptr->pickup_string_flags;
27211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(ptr->fallclk > 0) return; //Don't pick up a falling item
27212
27213
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(itemsbuf[id2].family == itype_progressive_itm)
27214 {
27215 int32_t newid = get_progressive_item(itemsbuf[id2]);
27216 if(newid > -1)
27217 {
27218 id2 = newid;
27219 holdid = newid;
27220 pstr = itemsbuf[newid].pstring;
27221 pstr_flags = itemsbuf[newid].pickup_string_flags;
27222 }
27223 }
27224
27225
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 bool bottledummy = (pickup&ipCHECK) && tmpscr[tmp].room == rBOTTLESHOP;
27226
27227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(bottledummy) //Dummy bullshit!
27228 {
27229 if(!game->canFillBottle())
27230 return;
27231 if(prices[PriceIndex]!=100000) // 100000 is a placeholder price for free items
27232 {
27233 if(!current_item_power(itype_wallet))
27234 {
27235 if( game->get_spendable_rupies()<abs(prices[PriceIndex]) ) return;
27236 int32_t tmpprice = -abs(prices[PriceIndex]);
27237 //game->change_drupy(-abs(prices[priceindex]));
27238 int32_t total = game->get_drupy()-tmpprice;
27239 total = vbound(total, 0, game->get_maxcounter(1)); //Never overflow! Overflow here causes subscreen bugs! -Z
27240 game->set_drupy(game->get_drupy()-total);
27241 }
27242 else //infinite wallet
27243 {
27244 game->change_drupy(0);
27245 }
27246 }
27247 boughtsomething=true;
27248 //make the other shop items untouchable after
27249 //you buy something
27250 int32_t count = 0;
27251
27252 for(int32_t i=0; i<3; i++)
27253 {
27254 if(QMisc.bottle_shop_types[tmpscr[tmp].catchall].fill[i] != 0)
27255 {
27256 ++count;
27257 }
27258 }
27259
27260 for(int32_t i=0; i<items.Count(); i++)
27261 {
27262 if(((item*)items.spr(i))->PriceIndex >-1 && i!=index)
27263 ((item*)items.spr(i))->pickup=ipDUMMY+ipFADE;
27264 }
27265
27266 int32_t slot = game->fillBottle(QMisc.bottle_shop_types[tmpscr[tmp].catchall].fill[PriceIndex]);
27267 id2 = find_bottle_for_slot(slot);
27268 ptr->id = id2;
27269 pstr = 0;
27270 pickup |= ipHOLDUP;
27271 }
27272 else
27273 {
27274 2 std::vector<int32_t> &ev = FFCore.eventData;
27275 2 ev.clear();
27276 2 ev.push_back(id2*10000);
27277 2 ev.push_back(pickup*10000);
27278 2 ev.push_back(pstr*10000);
27279 2 ev.push_back(pstr_flags*10000);
27280 2 ev.push_back(0);
27281 2 ev.push_back(ptr->getUID());
27282 2 ev.push_back(GENEVT_ICTYPE_COLLECT*10000);
27283 2 ev.push_back(0);
27284
27285 2 throwGenScriptEvent(GENSCR_EVENT_COLLECT_ITEM);
27286 2 bool nullify = ev[4] != 0;
27287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(nullify) return;
27288 2 id2 = ev[0]/10000;
27289 2 pickup = (pickup&(ipCHECK|ipDUMMY)) | (ev[1]/10000);
27290 2 pstr = ev[2] / 10000;
27291 2 pstr_flags = ev[3] / 10000;
27292
27293
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if(itemsbuf[id2].family == itype_bottlefill && !game->canFillBottle())
27294 return; //No picking these up unless you have a bottle to fill!
27295
27296
3/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2 if(((pickup&ipTIMER) && (ptr->clk2 < 32))&& !(pickup & ipCANGRAB))
27297 if(ptr->id!=iFairyMoving)
27298 // wait for it to stop flashing, doesn't check for other items yet
27299 return;
27300
27301
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(pickup&ipENEMY) // item was being carried by enemy
27302 if(more_carried_items()<=1) // 1 includes this own item.
27303 hasitem &= ~2;
27304
27305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(pickup&ipDUMMY) // dummy item (usually a rupee)
27306 {
27307 if(pickup&ipMONEY)
27308 dospecialmoney(index);
27309
27310 return;
27311 }
27312
27313
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if(get_bit(quest_rules,qr_HEARTSREQUIREDFIX) && !canget(id2))
27314 return;
27315
27316 2 int32_t nextitem = -1;
27317 2 do
27318 {
27319 2 nextitem = -1;
27320
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if((itemsbuf[id2].flags & ITEM_COMBINE) && game->get_item(id2))
27321 // Item upgrade routine.
27322 {
27323
27324 for(int32_t i=0; i<MAXITEMS; i++)
27325 {
27326 // Find the item which is as close to this item's fam_type as possible.
27327 if(itemsbuf[i].family==itemsbuf[id2].family && itemsbuf[i].fam_type>itemsbuf[id2].fam_type
27328 && (nextitem>-1 ? itemsbuf[i].fam_type<=itemsbuf[nextitem].fam_type : true))
27329 {
27330 nextitem = i;
27331 }
27332 }
27333
27334 if(nextitem>-1)
27335 {
27336 id2 = nextitem;
27337 if(get_bit(quest_rules,qr_ITEMCOMBINE_NEW_PSTR))
27338 {
27339 pstr = itemsbuf[id2].pstring;
27340 pstr_flags = itemsbuf[id2].pickup_string_flags;
27341 }
27342 if(!get_bit(quest_rules,qr_ITEMCOMBINE_CONTINUOUS))
27343 break; //no looping
27344 }
27345 }
27346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } while(nextitem > -1);
27347
27348
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(pickup&ipCHECK) // check restrictions
27349
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 switch(tmpscr[tmp].room)
27350 {
27351 case rSP_ITEM: // special item
27352
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(!canget(id2)) // These ones always need the Hearts Required check
27353 return;
27354
27355 1 break;
27356
27357 case rP_SHOP: // potion shop
27358 if(msg_active)
27359 return;
27360 [[fallthrough]];
27361 case rSHOP: // shop
27362 if(prices[PriceIndex]!=100000) // 100000 is a placeholder price for free items
27363 {
27364 if(!current_item_power(itype_wallet))
27365 {
27366 if( game->get_spendable_rupies()<abs(prices[PriceIndex]) ) return;
27367 int32_t tmpprice = -abs(prices[PriceIndex]);
27368 //game->change_drupy(-abs(prices[priceindex]));
27369 int32_t total = game->get_drupy()-tmpprice;
27370 total = vbound(total, 0, game->get_maxcounter(1)); //Never overflow! Overflow here causes subscreen bugs! -Z
27371 game->set_drupy(game->get_drupy()-total);
27372 }
27373 else //infinite wallet
27374 {
27375 game->change_drupy(0);
27376 }
27377 }
27378 boughtsomething=true;
27379 //make the other shop items untouchable after
27380 //you buy something
27381 int32_t count = 0;
27382
27383 for(int32_t i=0; i<3; i++)
27384 {
27385 if(QMisc.shop[tmpscr[tmp].catchall].hasitem[i] != 0)
27386 {
27387 ++count;
27388 }
27389 }
27390
27391 for(int32_t i=0; i<items.Count(); i++)
27392 {
27393 if(((item*)items.spr(i))->PriceIndex >-1 && i!=index)
27394 ((item*)items.spr(i))->pickup=ipDUMMY+ipFADE;
27395 }
27396
27397 break;
27398 1 }
27399
27400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(pickup&ipONETIME) // set mITEM for one-time-only items
27401 {
27402 setmapflag(mITEM);
27403
27404 //Okay so having old source files is a godsend. You wanna know why?
27405 //Because the issue here was never to so with the wrong flag being set; no it's always been setting the right flag.
27406 //The problem here is that guy rooms were always checking for getmapflag, which used to have an internal check for the default.
27407 //The default would be mITEM if currscr was under 128 (AKA not in a cave), and mSPECIALITEM if in a cave.
27408 //However, now the check just always defaults to mSPECIALITEM, which causes this bug.
27409 //This means that this section of code is no longer a bunch of eggshells, cause none of these overcomplicated compats actually solved shit lmao - Dimi
27410
27411 /*
27412 // WARNING - Item pickups are very volatile due to crazy compatability hacks, eg., supporting
27413 // broken behavior from early ZC versions. If you change things here please comment on it's purpose.
27414
27415 // some old quests need picking up a screen item to also disable the BELOW flag (for hunger rooms, etc)
27416 // What is etc?! We need to check for every valid state here. ~Gleeok
27417 if(get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW))
27418 {
27419 // Most older quests need one-time-pickups to not remove special items, etc.
27420 if(tmpscr->room==rGRUMBLE)
27421 {
27422 setmapflag(mSPECIALITEM);
27423 }
27424 }
27425 */
27426 }
27427
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 else if(pickup&ipONETIME2) // set mSPECIALITEM flag for other one-time-only items
27428
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 setmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM);
27429
27430
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if(exstate > -1 && exstate < 32)
27431 {
27432 setxmapflag(1<<exstate);
27433 }
27434
27435
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(pickup&ipSECRETS) // Trigger secrets if this item has the secret pickup
27436 {
27437 if(tmpscr->flags9&fITEMSECRETPERM) setmapflag(mSECRET);
27438 hidden_entrance(0, true, false, -5);
27439 }
27440
27441 2 collectitem_script(id2);
27442 2 getitem(id2, false, true);
27443 }
27444
27445
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(pickup&ipHOLDUP)
27446 {
27447 1 attackclk=0;
27448 1 reset_swordcharge();
27449
27450
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if(action!=swimming && !IsSideSwim())
27451 1 reset_hookshot();
27452
27453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(msg_onscreen)
27454 {
27455 1 dismissmsg();
27456 1 }
27457
27458 1 clear_bitmap(pricesdisplaybuf);
27459
27460
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1 if(get_bit(quest_rules, qr_OLDPICKUP) || ((tmpscr[tmp].room==rSP_ITEM || tmpscr[tmp].room==rRP_HC || tmpscr[tmp].room==rTAKEONE) && (pickup&ipONETIME2)) ||
27461 (get_bit(quest_rules, qr_SHOP_ITEMS_VANISH) && (tmpscr[tmp].room==rBOTTLESHOP || tmpscr[tmp].room==rSHOP) && (pickup&ipCHECK)))
27462 {
27463 1 fadeclk=66;
27464 1 }
27465
27466
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if(id2!=iBombs || action==swimming || get_bit(quest_rules,qr_BOMBHOLDFIX))
27467 {
27468 // don't hold up bombs unless swimming or the bomb hold fix quest rule is on
27469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(action==swimming)
27470 {
27471 action=waterhold1; FFCore.setHeroAction(waterhold1);
27472 }
27473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if(IsSideSwim())
27474 {
27475 action=sidewaterhold1; FFCore.setHeroAction(sidewaterhold1);
27476 }
27477 else
27478 {
27479 1 action=landhold1; FFCore.setHeroAction(landhold1);
27480 }
27481
27482
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(ptr->twohand)
27483 {
27484 if(action==waterhold1)
27485 {
27486 action=waterhold2; FFCore.setHeroAction(waterhold2);
27487 }
27488 else if(action==sidewaterhold1)
27489 {
27490 action=sidewaterhold2; FFCore.setHeroAction(sidewaterhold2);
27491 }
27492 else
27493 {
27494 action=landhold2; FFCore.setHeroAction(landhold2);
27495 }
27496 }
27497
27498 1 holdclk=130;
27499
27500 //restart music
27501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(get_bit(quest_rules, qr_HOLDNOSTOPMUSIC) == 0)
27502 1 music_stop();
27503
27504 1 holditem=holdid; // NES consistency: when combining blue potions, hold up the blue potion.
27505 1 freeze_guys=true;
27506 //show the info string
27507
27508
27509 //if (pstr > 0 ) //&& itemsbuf[index].pstring < msg_count && ( ( itemsbuf[index].pickup_string_flags&itemdataPSTRING_ALWAYS || itemsbuf[index].pickup_string_flags&itemdataPSTRING_IP_HOLDUP ) ) )
27510
27511 1 int32_t shop_pstr = 0;
27512
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (PriceIndex > -1)
27513 {
27514 switch(tmpscr[tmp].room)
27515 {
27516 case rSHOP:
27517 shop_pstr = QMisc.shop[tmpscr[tmp].catchall].str[PriceIndex];
27518 break;
27519 case rBOTTLESHOP:
27520 shop_pstr = QMisc.bottle_shop_types[tmpscr[tmp].catchall].str[PriceIndex];
27521 break;
27522 }
27523 }
27524
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if ( (pstr > 0 && pstr < msg_count) || (shop_pstr > 0 && shop_pstr < msg_count) )
27525 {
27526 if ( (pstr > 0 && pstr < msg_count) && ( ( ( pstr_flags&itemdataPSTRING_ALWAYS || pstr_flags&itemdataPSTRING_NOMARK || pstr_flags&itemdataPSTRING_IP_HOLDUP || (!(FFCore.GetItemMessagePlayed(id2))) ) ) ) )
27527 {
27528 if ( (!(pstr_flags&itemdataPSTRING_NOMARK)) ) FFCore.SetItemMessagePlayed(id2);
27529 }
27530 else pstr = 0;
27531 if(shop_pstr)
27532 {
27533 donewmsg(shop_pstr);
27534 enqueued_str = pstr;
27535 }
27536 else if(pstr)
27537 {
27538 donewmsg(pstr);
27539 }
27540 }
27541
27542 1 }
27543
27544
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if(itemsbuf[id2].family!=itype_triforcepiece || !(itemsbuf[id2].flags & ITEM_GAMEDATA))
27545 {
27546 1 sfx(tmpscr[0].holdupsfx);
27547 1 }
27548
27549 1 ptr->set_forcegrab(false);
27550 1 items.del(index);
27551
27552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 for(int32_t i=0; i<Lwpns.Count(); i++)
27553 {
27554 weapon *w = (weapon*)Lwpns.spr(i);
27555
27556 if(w->dragging==index)
27557 {
27558 w->dragging=-1;
27559 }
27560 else if(w->dragging>index)
27561 {
27562 w->dragging-=1;
27563 }
27564 }
27565
27566 // clear up shop stuff
27567
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if((isdungeon()==0)&&(index!=0))
27568 {
27569 if(boughtsomething)
27570 {
27571 fadeclk=66;
27572
27573 if(((item*)items.spr(0))->id == iRupy && ((item*)items.spr(0))->pickup & ipDUMMY)
27574 {
27575 items.del(0);
27576
27577 for(int32_t i=0; i<Lwpns.Count(); i++)
27578 {
27579 weapon *w = (weapon*)Lwpns.spr(i);
27580
27581 if(w->dragging==0)
27582 {
27583 w->dragging=-1;
27584 }
27585 else if(w->dragging>0)
27586 {
27587 w->dragging-=1;
27588 }
27589 }
27590 }
27591 }
27592
27593 if(msg_onscreen)
27594 {
27595 dismissmsg();
27596 }
27597
27598 clear_bitmap(pricesdisplaybuf);
27599 set_clip_state(pricesdisplaybuf, 1);
27600 }
27601
27602 // items.del(index);
27603 1 }
27604 else
27605 {
27606 1 ptr->set_forcegrab(false);
27607 1 items.del(index);
27608
27609
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for(int32_t i=0; i<Lwpns.Count(); i++)
27610 {
27611 1 weapon *w = (weapon*)Lwpns.spr(i);
27612
27613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(w->dragging==index)
27614 {
27615 w->dragging=-1;
27616 }
27617
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if(w->dragging>index)
27618 {
27619 w->dragging-=1;
27620 }
27621 1 }
27622
27623
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(msg_onscreen)
27624 {
27625 dismissmsg();
27626 }
27627
27628 //general item pickup message
27629 //show the info string
27630 //non-held
27631 //if ( pstr > 0 ) //&& itemsbuf[index].pstring < msg_count && ( ( itemsbuf[index].pickup_string_flags&itemdataPSTRING_ALWAYS || (!(FFCore.GetItemMessagePlayed(index))) ) ) )
27632
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 int32_t shop_pstr = ( tmpscr[tmp].room == rSHOP && PriceIndex>=0 && QMisc.shop[tmpscr[tmp].catchall].str[PriceIndex] > 0 ) ? QMisc.shop[tmpscr[tmp].catchall].str[PriceIndex] : 0;
27633
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if ( (pstr > 0 && pstr < msg_count) || (shop_pstr > 0 && shop_pstr < msg_count) )
27634 {
27635 if ( (pstr > 0 && pstr < msg_count) && ( (!(pstr_flags&itemdataPSTRING_IP_HOLDUP)) && ( pstr_flags&itemdataPSTRING_NOMARK || pstr_flags&itemdataPSTRING_ALWAYS || (!(FFCore.GetItemMessagePlayed(id2))) ) ) )
27636 {
27637 if ( (!(pstr_flags&itemdataPSTRING_NOMARK)) ) FFCore.SetItemMessagePlayed(id2);
27638 }
27639 else pstr = 0;
27640 if(shop_pstr)
27641 {
27642 donewmsg(shop_pstr);
27643 enqueued_str = pstr;
27644 }
27645 else if(pstr)
27646 {
27647 donewmsg(pstr);
27648 }
27649 }
27650
27651
27652 1 clear_bitmap(pricesdisplaybuf);
27653 1 set_clip_state(pricesdisplaybuf, 1);
27654 }
27655
27656
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(itemsbuf[id2].family==itype_triforcepiece)
27657 {
27658 if(itemsbuf[id2].misc2>0) //Small TF Piece
27659 {
27660 getTriforce(id2);
27661 }
27662 else
27663 {
27664 if (ptr->linked_parent == eeGANON) game->lvlitems[dlevel]|=liBOSS;
27665 getBigTri(id2);
27666 }
27667 }
27668 1888 }
27669
27670 void HeroClass::StartRefill(int32_t refillWhat)
27671 {
27672 if(!refilling)
27673 {
27674 refillclk=21;
27675 stop_sfx(QMisc.miscsfx[sfxLOWHEART]);
27676 sfx(WAV_REFILL,128,true);
27677 refilling=refillWhat;
27678 if(FFCore.quest_format[vZelda] < 0x255)
27679 {
27680 //Yes, this isn't a QR check. This was implemented before the QRs got bumped up.
27681 //I attempted to change this check to a quest rule, but here's the issue: this affects
27682 //triforces and potions as well, not just fairy flags. This means that having a compat rule
27683 //would result in a rule that is checked by default for every tileset or quest made before
27684 //2.55, one in a place most people won't check. That means that if they were to go to use
27685 //the new potion or triforce flags for jinx curing behavior, they'd find that it doesn't work,
27686 //all because of an obscure compat rule being checked. Most peoples instincts are sadly not
27687 //"go through the compat rules and turn them all off", so this remains a version check instead
27688 //of a qr check. Don't make my mistake and waste time trying to change this in vain. -Deedee
27689 Start250Refill(refillWhat);
27690 }
27691 else //use 2.55+ behavior
27692 {
27693 if(refill_why>=0) // Item index
27694 {
27695 if(itemsbuf[refill_why].family==itype_potion)
27696 {
27697 if(itemsbuf[refill_why].flags & ITEM_FLAG3){swordclk=0;verifyAWpn();}
27698 if(itemsbuf[refill_why].flags & ITEM_FLAG4)itemclk=0;
27699 }
27700 else if(itemsbuf[refill_why].family==itype_triforcepiece)
27701 {
27702 if(itemsbuf[refill_why].flags & ITEM_FLAG3){swordclk=0;verifyAWpn();}
27703 if(itemsbuf[refill_why].flags & ITEM_FLAG4)itemclk=0;
27704 }
27705 }
27706 else if(refill_why==REFILL_FAIRY)
27707 {
27708 if(!get_bit(quest_rules,qr_NONBUBBLEFAIRIES)){swordclk=0;verifyAWpn();}
27709 if(get_bit(quest_rules,qr_ITEMBUBBLE))itemclk=0;
27710 }
27711 }
27712 }
27713 }
27714
27715 void HeroClass::Start250Refill(int32_t refillWhat)
27716 {
27717 if(!refilling)
27718 {
27719 refillclk=21;
27720 stop_sfx(QMisc.miscsfx[sfxLOWHEART]);
27721 sfx(WAV_REFILL,128,true);
27722 refilling=refillWhat;
27723
27724 if(refill_why>=0) // Item index
27725 {
27726 if((itemsbuf[refill_why].family==itype_potion)&&(!get_bit(quest_rules,qr_NONBUBBLEMEDICINE)))
27727 {
27728 swordclk=0;
27729 verifyAWpn();
27730 if(get_bit(quest_rules,qr_ITEMBUBBLE)) itemclk=0;
27731 }
27732
27733 if((itemsbuf[refill_why].family==itype_triforcepiece)&&(!get_bit(quest_rules,qr_NONBUBBLETRIFORCE)))
27734 {
27735 swordclk=0;
27736 verifyAWpn();
27737 if(get_bit(quest_rules,qr_ITEMBUBBLE)) itemclk=0;
27738 }
27739 }
27740 else if((refill_why==REFILL_FAIRY)&&(!get_bit(quest_rules,qr_NONBUBBLEFAIRIES)))
27741 {
27742 swordclk=0;
27743 verifyAWpn();
27744 if(get_bit(quest_rules,qr_ITEMBUBBLE)) itemclk=0;
27745 }
27746 }
27747 }
27748
27749 bool HeroClass::refill()
27750 {
27751 if(refilling==REFILL_NONE || refilling==REFILL_FAIRYDONE)
27752 {
27753 return false;
27754 }
27755
27756 ++refillclk;
27757 int32_t speed = get_bit(quest_rules,qr_FASTFILL) ? 6 : 22;
27758 int32_t refill_heart_stop=game->get_maxlife();
27759 int32_t refill_magic_stop=game->get_maxmagic();
27760
27761 if(refill_why>=0 && itemsbuf[refill_why].family==itype_potion)
27762 {
27763 refill_heart_stop=zc_min(potion_life+(itemsbuf[refill_why].flags & ITEM_FLAG1 ?int32_t(game->get_maxlife()*(itemsbuf[refill_why].misc1 /100.0)):((itemsbuf[refill_why].misc1 *game->get_hp_per_heart()))),game->get_maxlife());
27764 refill_magic_stop=zc_min(potion_magic+(itemsbuf[refill_why].flags & ITEM_FLAG2 ?int32_t(game->get_maxmagic()*(itemsbuf[refill_why].misc2 /100.0)):((itemsbuf[refill_why].misc2 *game->get_mp_per_block()))),game->get_maxmagic());
27765 }
27766
27767 if(refillclk%speed == 0)
27768 {
27769 // game->life&=0xFFC;
27770 switch(refill_what)
27771 {
27772 case REFILL_LIFE:
27773 game->set_life(zc_min(refill_heart_stop, (game->get_life()+game->get_hp_per_heart()/2)));
27774
27775 if(game->get_life()>=refill_heart_stop)
27776 {
27777 game->set_life(refill_heart_stop);
27778 //kill_sfx(); //this 1. needs to be pause resme, and 2. needs an item flag.
27779 for ( int32_t q = 0; q < WAV_COUNT; q++ )
27780 {
27781 if ( q == (int32_t)tmpscr->oceansfx ) continue;
27782 if ( q == (int32_t)tmpscr->bosssfx ) continue;
27783 stop_sfx(q);
27784 }
27785 sfx(QMisc.miscsfx[sfxREFILL]);
27786 refilling=REFILL_NONE;
27787 return false;
27788 }
27789
27790 break;
27791
27792 case REFILL_MAGIC:
27793 game->set_magic(zc_min(refill_magic_stop, (game->get_magic()+game->get_mp_per_block()/4)));
27794
27795 if(game->get_magic()>=refill_magic_stop)
27796 {
27797 game->set_magic(refill_magic_stop);
27798 //kill_sfx(); //this 1. needs to be pause resme, and 2. needs an item flag.
27799 for ( int32_t q = 0; q < WAV_COUNT; q++ )
27800 {
27801 if ( q == (int32_t)tmpscr->oceansfx ) continue;
27802 if ( q == (int32_t)tmpscr->bosssfx ) continue;
27803 stop_sfx(q);
27804 }
27805 sfx(QMisc.miscsfx[sfxREFILL]);
27806 refilling=REFILL_NONE;
27807 return false;
27808 }
27809
27810 break;
27811
27812 case REFILL_ALL:
27813 game->set_life(zc_min(refill_heart_stop, (game->get_life()+game->get_hp_per_heart()/2)));
27814 game->set_magic(zc_min(refill_magic_stop, (game->get_magic()+game->get_mp_per_block()/4)));
27815
27816 if((game->get_life()>=refill_heart_stop)&&(game->get_magic()>=refill_magic_stop))
27817 {
27818 game->set_life(refill_heart_stop);
27819 game->set_magic(refill_magic_stop);
27820 //kill_sfx(); //this 1. needs to be pause resme, and 2. needs an item flag.
27821 for ( int32_t q = 0; q < WAV_COUNT; q++ )
27822 {
27823 if ( q == (int32_t)tmpscr->oceansfx ) continue;
27824 if ( q == (int32_t)tmpscr->bosssfx ) continue;
27825 stop_sfx(q);
27826 }
27827 sfx(QMisc.miscsfx[sfxREFILL]);
27828 refilling=REFILL_NONE;
27829 return false;
27830 }
27831
27832 break;
27833 }
27834 }
27835
27836 return true;
27837 }
27838
27839 void HeroClass::getTriforce(int32_t id2)
27840 {
27841
27842 PALETTE flash_pal;
27843 int32_t refill_frame = ( (itemsbuf[id2].misc5 > 0) ? itemsbuf[id2].misc5 : 88 );
27844
27845 for(int32_t i=0; i<256; i++)
27846 {
27847 flash_pal[i] = get_bit(quest_rules,qr_FADE) ? _RGB(63,63,0) : _RGB(63,63,63);
27848 }
27849
27850
27851
27852 //get rid off all sprites but Hero
27853 guys.clear();
27854 items.clear();
27855 Ewpns.clear();
27856 Lwpns.clear();
27857 Sitems.clear();
27858 chainlinks.clear();
27859
27860 //decorations.clear();
27861 if(!COOLSCROLL)
27862 {
27863 show_subscreen_items=false;
27864 }
27865
27866 sfx(itemsbuf[id2].playsound);
27867 if ( !(itemsbuf[id2].flags & ITEM_FLAG11) ) music_stop();
27868
27869 //If item flag six is enabled, and a sound is set to attributes[2], play that sound.
27870 if ( (itemsbuf[id2].flags & ITEM_FLAG14) )
27871 {
27872 uint8_t playwav = itemsbuf[id2].misc3;
27873 //zprint2("playwav is: %d\n", playwav);
27874 sfx(playwav);
27875
27876 }
27877
27878 //itemsbuf[id2].flags & ITEM_FLAG9 : Don't dismiss Messages
27879 //itemsbuf[id2].flags & ITEM_FLAG10 : Cutscene interrupts action script..
27880 //itemsbuf[id2].flags & ITEM_FLAG11 : Don't change music.
27881 //itemsbuf[id2].flags & ITEM_FLAG12 : Run Collect Script Script On Collection
27882 //itemsbuf[id2].flags & ITEM_FLAG13 : Run Action Script On Collection
27883 //itemsbuf[id2].flags & ITEM_FLAG14 : Play second sound (WAV) from Attributes[2] (misc2)
27884 //itemsbuf[id2].flags & ITEM_FLAG15 : No MIDI
27885
27886 if(!(itemsbuf[id2].flags & ITEM_FLAG15)) //No MIDI flag
27887 {
27888 if(itemsbuf[id2].misc1)
27889 jukebox(itemsbuf[id2].misc1+ZC_MIDI_COUNT-1);
27890 else
27891 try_zcmusic((char*)moduledata.base_NSF_file,moduledata.tf_track, ZC_MIDI_TRIFORCE);
27892 }
27893 if(itemsbuf[id2].flags & ITEM_GAMEDATA)
27894 {
27895 game->lvlitems[dlevel]|=liTRIFORCE;
27896 }
27897
27898 int32_t f=0;
27899 int32_t x2=0;
27900 int32_t curtain_x=0;
27901 int32_t c=0;
27902 /*if ( (itemsbuf[id2].flags & ITEM_FLAG12) ) //Run collect script This happens w/o the flag.
27903 {
27904 if(itemsbuf[id2].collect_script && !item_collect_doscript[id2])
27905 {
27906 //clear the item script stack for a new script
27907 ri = &(itemCollectScriptData[id2]);
27908 for ( int32_t q = 0; q < 1024; q++ ) item_collect_stack[id2][q] = 0xFFFF;
27909 ri->Clear();
27910 //itemCollectScriptData[(id2 & 0xFFF)].Clear();
27911 //for ( int32_t q = 0; q < 1024; q++ ) item_collect_stack[(id2 & 0xFFF)][q] = 0;
27912 //ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[id2].collect_script, ((id2 & 0xFFF)*-1));
27913 if ( id2 > 0 && !item_collect_doscript[id2] ) //No collect script on item 0.
27914 {
27915 item_collect_doscript[id2] = 1;
27916 itemscriptInitialised[id2] = 0;
27917 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[id2].collect_script, ((id2)*-1));
27918 //if ( !get_bit(quest_rules, qr_ITEMSCRIPTSKEEPRUNNING) )
27919 FFCore.deallocateAllArrays(SCRIPT_ITEM,-(id2));
27920 }
27921 else if (!id2 && !item_collect_doscript[id2]) //item 0
27922 {
27923 item_collect_doscript[id2] = 1;
27924 itemscriptInitialised[id2] = 0;
27925 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[id2].collect_script, COLLECT_SCRIPT_ITEM_ZERO);
27926 //if ( !get_bit(quest_rules, qr_ITEMSCRIPTSKEEPRUNNING) )
27927 FFCore.deallocateAllArrays(SCRIPT_ITEM,COLLECT_SCRIPT_ITEM_ZERO);
27928 }
27929 }
27930 }
27931 */
27932 do
27933 {
27934
27935
27936 if ( (itemsbuf[id2].flags & ITEM_FLAG13) ) //Run action script on collection.
27937 {
27938 if ( itemsbuf[id2].script )
27939 {
27940 if ( !item_doscript[id2] )
27941 {
27942 ri = &(itemScriptData[id2]);
27943 for ( int32_t q = 0; q < 1024; q++ ) item_stack[id2][q] = 0xFFFF;
27944 ri->Clear();
27945 item_doscript[id2] = 1;
27946 itemscriptInitialised[id2] = 0;
27947 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[id2].script, id2);
27948 FFCore.deallocateAllArrays(SCRIPT_ITEM,(id2));
27949 }
27950 else
27951 {
27952 if ( !(itemsbuf[id2].flags & ITEM_FLAG10) ) //Cutscene halts the script it resumes after cutscene.
27953 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[id2].script, id2); //if flag is off, run the script every frame of the cutscene.
27954 }
27955 }
27956 }
27957 //if ( itemsbuf[id2].misc2 == 2 ) //No cutscene; what if people used '2' on older quests?
27958 if ( (itemsbuf[id2].flags & ITEM_FLAG12) ) //No cutscene
27959 {
27960 return;
27961 }
27962 if(f==40)
27963 {
27964 actiontype oldaction = action;
27965 ALLOFF((!(itemsbuf[id2].flags & ITEM_FLAG9)), false);
27966 action=oldaction; // have to reset this flag
27967 FFCore.setHeroAction(oldaction);
27968 }
27969
27970
27971 if(f>=40 && f<88)
27972 {
27973 if(get_bit(quest_rules,qr_FADE))
27974 {
27975 //int32_t flashbit = ;
27976 if((f&(((get_bit(quest_rules,qr_EPILEPSY) || epilepsyFlashReduction)) ? 6 : 3))==0)
27977 {
27978 fade_interpolate(RAMpal,flash_pal,RAMpal,42,0,CSET(6)-1);
27979 refreshpal=true;
27980 }
27981
27982 if((f&3)==2)
27983 {
27984 loadpalset(0,0);
27985 loadpalset(1,1);
27986 loadpalset(5,5);
27987
27988 if(currscr<128) loadlvlpal(DMaps[currdmap].color);
27989 else loadlvlpal(0xB); // TODO: Cave/Item Cellar distinction?
27990 }
27991 }
27992 else
27993 {
27994 if((f&((get_bit(quest_rules,qr_EPILEPSY)) ? 10 : 7))==0)
27995 {
27996 for(int32_t cs2=2; cs2<5; cs2++)
27997 {
27998 for(int32_t i=1; i<16; i++)
27999 {
28000 RAMpal[CSET(cs2)+i]=flash_pal[CSET(cs2)+i];
28001 }
28002 }
28003
28004 refreshpal=true;
28005 }
28006
28007 if((f&7)==4)
28008 {
28009 if(currscr<128) loadlvlpal(DMaps[currdmap].color);
28010 else loadlvlpal(0xB);
28011
28012 loadpalset(5,5);
28013 }
28014 }
28015 }
28016
28017
28018 if(itemsbuf[id2].flags & ITEM_GAMEDATA)
28019 {
28020 if(f==refill_frame)
28021 {
28022 refill_what=REFILL_ALL;
28023 refill_why=id2;
28024 StartRefill(REFILL_ALL);
28025 refill();
28026 }
28027
28028 if(f==(refill_frame+1))
28029 {
28030 if(refill())
28031 {
28032 --f;
28033 }
28034 }
28035 }
28036
28037 if(itemsbuf[id2].flags & ITEM_FLAG1) // Warp out flag
28038 {
28039 if(f>=208 && f<288)
28040 {
28041 ++x2;
28042
28043 switch(++c)
28044 {
28045 case 5:
28046 c=0;
28047 [[fallthrough]];
28048 case 0:
28049 case 2:
28050 case 3:
28051 ++x2;
28052 break;
28053 }
28054 }
28055
28056 do_dcounters();
28057
28058 if(f<288)
28059 {
28060 curtain_x=x2&0xF8;
28061 draw_screen_clip_rect_x1=curtain_x;
28062 draw_screen_clip_rect_x2=255-curtain_x;
28063 draw_screen_clip_rect_y1=0;
28064 draw_screen_clip_rect_y2=223;
28065 //draw_screen(tmpscr);
28066 }
28067 }
28068
28069 draw_screen(tmpscr);
28070 //this causes bugs
28071 //the subscreen appearing over the curtain effect should now be fixed in draw_screen
28072 //so this is not necessary -DD
28073 //put_passive_subscr(framebuf,&QMisc,0,passive_subscreen_offset,false,false);
28074
28075 //Run Triforce Script
28076 advanceframe(true);
28077 ++f;
28078 }
28079 while
28080 (
28081 (f < ( (itemsbuf[id2].misc4 > 0) ? itemsbuf[id2].misc4 : 408))
28082 || (!(itemsbuf[id2].flags & ITEM_FLAG15) /*&& !(itemsbuf[id2].flags & ITEM_FLAG11)*/ && (midi_pos > 0 && !replay_is_active()))
28083 || (/*!(itemsbuf[id2].flags & ITEM_FLAG15) &&*/ !(itemsbuf[id2].flags & ITEM_FLAG11) && (zcmusic!=NULL) && (zcmusic->position<800 && !replay_is_active())
28084 // Music is played at the same speed when fps is uncapped, so in replay mode we need to ignore the music position and instead
28085 // just count frames. 480 is the number of frames it takes for the triforce song in classic_1st.qst to finish playing, but the exact
28086 // value doesn't matter.
28087 || (replay_is_active() && f < 480) )
28088 ); // 800 may not be just right, but it works
28089
28090 action=none; FFCore.setHeroAction(none);
28091 holdclk=0;
28092 draw_screen_clip_rect_x1=0;
28093 draw_screen_clip_rect_x2=255;
28094 draw_screen_clip_rect_y1=0;
28095 draw_screen_clip_rect_y2=223;
28096 show_subscreen_items=true;
28097
28098 //Warp Hero out of item cellars, in 2.10 and earlier quests. -Z ( 16th January, 2019 )
28099 //Added a QR for this, to Other->2, as `Triforce in Cellar Warps Hero Out`. -Z 15th March, 2019
28100 if(itemsbuf[id2].flags & ITEM_FLAG1 && ( get_bit(quest_rules,qr_SIDEVIEWTRIFORCECELLAR) ? ( currscr < MAPSCRS192b136 ) : (currscr < MAPSCRSNORMAL) ) )
28101 {
28102 sdir=dir;
28103 dowarp(1,0); //side warp
28104 }
28105 else
28106 {
28107 if ( !(itemsbuf[id2].flags & ITEM_FLAG11) ) playLevelMusic();
28108 }
28109 }
28110
28111 void red_shift()
28112 {
28113 int32_t tnum=176;
28114
28115 // set up the new palette
28116 for(int32_t i=CSET(2); i < CSET(4); i++)
28117 {
28118 int32_t r = (i-CSET(2)) << 1;
28119 RAMpal[i+tnum].r = r;
28120 RAMpal[i+tnum].g = r >> 3;
28121 RAMpal[i+tnum].b = r >> 4;
28122 }
28123
28124 // color scale the game screen
28125 for(int32_t y=0; y<168; y++)
28126 {
28127 for(int32_t x=0; x<256; x++)
28128 {
28129 int32_t c = framebuf->line[y+playing_field_offset][x];
28130 int32_t r = zc_min(int32_t(RAMpal[c].r*0.4 + RAMpal[c].g*0.6 + RAMpal[c].b*0.4)>>1,31);
28131 framebuf->line[y+playing_field_offset][x] = (c ? (r+tnum+CSET(2)) : 0);
28132 }
28133 }
28134
28135 refreshpal = true;
28136 }
28137
28138
28139
28140 void setup_red_screen_old()
28141 {
28142 clear_bitmap(framebuf);
28143 rectfill(scrollbuf, 0, 0, 255, 167, 0);
28144
28145 if(XOR(tmpscr->flags7&fLAYER2BG, DMaps[currdmap].flags&dmfLAYER2BG)) do_layer(scrollbuf, 0, 2, tmpscr, 0, playing_field_offset, 2);
28146
28147 if(XOR(tmpscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG)) do_layer(scrollbuf, 0, 3, tmpscr, 0, playing_field_offset, 2);
28148
28149 putscr(scrollbuf, 0, 0, tmpscr);
28150 putscrdoors(scrollbuf,0,0,tmpscr);
28151 blit(scrollbuf, framebuf, 0, 0, 0, playing_field_offset, 256, 168);
28152 do_layer(framebuf, 0, 1, tmpscr, 0, 0, 2);
28153
28154 if(!(XOR(tmpscr->flags7&fLAYER2BG, DMaps[currdmap].flags&dmfLAYER2BG))) do_layer(framebuf, 0, 2, tmpscr, 0, 0, 2);
28155
28156 do_layer(framebuf, -2, 0, tmpscr, 0, 0, 2);
28157 if(get_bit(quest_rules, qr_PUSHBLOCK_LAYER_1_2))
28158 {
28159 do_layer(framebuf, -2, 1, tmpscr, 0, 0, 2);
28160 do_layer(framebuf, -2, 2, tmpscr, 0, 0, 2);
28161 }
28162
28163 if(!(msg_bg_display_buf->clip))
28164 {
28165 blit_msgstr_bg(framebuf, 0, 0, 0, playing_field_offset, 256, 168);
28166 }
28167
28168 if(!(msg_portrait_display_buf->clip))
28169 {
28170 blit_msgstr_prt(framebuf, 0, 0, 0, playing_field_offset, 256, 168);
28171 }
28172
28173 if(!(msg_txt_display_buf->clip))
28174 {
28175 blit_msgstr_fg(framebuf, 0, 0, 0, playing_field_offset, 256, 168);
28176 }
28177
28178 if(!(pricesdisplaybuf->clip))
28179 {
28180 masked_blit(pricesdisplaybuf, framebuf,0,0,0,playing_field_offset, 256,168);
28181 }
28182
28183 //red shift
28184 // color scale the game screen
28185 for(int32_t y=0; y<168; y++)
28186 {
28187 for(int32_t x=0; x<256; x++)
28188 {
28189 int32_t c = framebuf->line[y+playing_field_offset][x];
28190 int32_t r = zc_min(int32_t(RAMpal[c].r*0.4 + RAMpal[c].g*0.6 + RAMpal[c].b*0.4)>>1,31);
28191 framebuf->line[y+playing_field_offset][x] = (c ? (r+CSET(2)) : 0);
28192 }
28193 }
28194
28195 // Hero->draw(framebuf);
28196 blit(framebuf,scrollbuf, 0, playing_field_offset, 256, playing_field_offset, 256, 168);
28197
28198 clear_bitmap(framebuf);
28199
28200 if(!((tmpscr->layermap[2]==0||(XOR(tmpscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG)))
28201 && tmpscr->layermap[3]==0
28202 && tmpscr->layermap[4]==0
28203 && tmpscr->layermap[5]==0
28204 && !overheadcombos(tmpscr)))
28205 {
28206 if(!(XOR(tmpscr->flags7&fLAYER3BG, DMaps[currdmap].flags&dmfLAYER3BG))) do_layer(framebuf, 0, 3, tmpscr, 0, 0, 2);
28207
28208 do_layer(framebuf, 0, 4, tmpscr, 0, 0, 2);
28209 do_layer(framebuf, -1, 0, tmpscr, 0, 0, 2);
28210 if(get_bit(quest_rules, qr_OVERHEAD_COMBOS_L1_L2))
28211 {
28212 do_layer(framebuf, -1, 1, tmpscr, 0, 0, 2);
28213 do_layer(framebuf, -1, 2, tmpscr, 0, 0, 2);
28214 }
28215 do_layer(framebuf, 0, 5, tmpscr, 0, 0, 2);
28216 do_layer(framebuf, 0, 6, tmpscr, 0, 0, 2);
28217
28218 //do an AND masked blit for messages on top of layers
28219 if(!(msg_txt_display_buf->clip) || !(msg_bg_display_buf->clip) || !(pricesdisplaybuf->clip) || !(msg_portrait_display_buf->clip))
28220 {
28221 BITMAP* subbmp = create_bitmap_ex(8,256,168);
28222 clear_bitmap(subbmp);
28223 if(!(msg_txt_display_buf->clip) || !(msg_bg_display_buf->clip) || !(msg_portrait_display_buf->clip))
28224 {
28225 masked_blit(framebuf, subbmp, 0, playing_field_offset, 0, 0, 256, 168);
28226 if(!(msg_bg_display_buf->clip)) blit_msgstr_bg(subbmp, 0, 0, 0, 0, 256, 168);
28227 if(!(msg_portrait_display_buf->clip)) blit_msgstr_prt(subbmp, 0, 0, 0, 0, 256, 168);
28228 if(!(msg_txt_display_buf->clip)) blit_msgstr_fg(subbmp, 0, 0, 0, 0, 256, 168);
28229 }
28230 for(int32_t y=0; y<168; y++)
28231 {
28232 for(int32_t x=0; x<256; x++)
28233 {
28234 int32_t c1 = framebuf->line[y+playing_field_offset][x];
28235 int32_t c2 = subbmp->line[y][x];
28236 int32_t c3 = pricesdisplaybuf->clip ? 0 : pricesdisplaybuf->line[y][x];
28237
28238 if(c1 && c3)
28239 {
28240 framebuf->line[y+playing_field_offset][x] = c3;
28241 }
28242 else if(c1 && c2)
28243 {
28244 framebuf->line[y+playing_field_offset][x] = c2;
28245 }
28246 }
28247 }
28248 destroy_bitmap(subbmp);
28249 }
28250
28251 //red shift
28252 // color scale the game screen
28253 for(int32_t y=0; y<168; y++)
28254 {
28255 for(int32_t x=0; x<256; x++)
28256 {
28257 int32_t c = framebuf->line[y+playing_field_offset][x];
28258 int32_t r = zc_min(int32_t(RAMpal[c].r*0.4 + RAMpal[c].g*0.6 + RAMpal[c].b*0.4)>>1,31);
28259 framebuf->line[y+playing_field_offset][x] = r+CSET(2);
28260 }
28261 }
28262 }
28263
28264 blit(framebuf,scrollbuf, 0, playing_field_offset, 0, playing_field_offset, 256, 168);
28265
28266 // set up the new palette
28267 for(int32_t i=CSET(2); i < CSET(4); i++)
28268 {
28269 int32_t r = (i-CSET(2)) << 1;
28270 RAMpal[i].r = r;
28271 RAMpal[i].g = r >> 3;
28272 RAMpal[i].b = r >> 4;
28273 }
28274
28275 refreshpal = true;
28276 }
28277
28278
28279
28280 void slide_in_color(int32_t color)
28281 {
28282 for(int32_t i=1; i<16; i+=3)
28283 {
28284 RAMpal[CSET(2)+i+2] = RAMpal[CSET(2)+i+1];
28285 RAMpal[CSET(2)+i+1] = RAMpal[CSET(2)+i];
28286 RAMpal[CSET(2)+i] = NESpal(color);
28287 }
28288
28289 refreshpal=true;
28290 }
28291
28292
28293 void HeroClass::heroDeathAnimation()
28294 {
28295 int32_t f=0;
28296 int32_t deathclk=0,deathfrm=0;
28297
28298 action=none; FFCore.setHeroAction(dying); //mayhaps a new action of 'gameover'? -Z
28299
28300 kill_sfx(); //call before the onDeath script.
28301
28302 //do
28303 //{
28304
28305 // ZScriptVersion::RunScript(SCRIPT_PLAYER, SCRIPT_PLAYER_DEATH, SCRIPT_PLAYER_DEATH);
28306 // FFCore.Waitframe();
28307 //}while(player_doscript);
28308 //ZScriptVersion::RunScript(SCRIPT_PLAYER, SCRIPT_PLAYER_DEATH, SCRIPT_PLAYER_DEATH);
28309 //while(player_doscript) { advanceframe(true); } //Not safe. The script runs for only one frame at present.
28310
28311 //Playing=false;
28312 if(!debug_enabled)
28313 {
28314 Paused=false;
28315 }
28316
28317 /*
28318 game->set_deaths(zc_min(game->get_deaths()+1,999));
28319 dir=down;
28320 music_stop();
28321
28322 attackclk=hclk=superman=0;
28323 scriptcoldet = 1;
28324
28325 for(int32_t i=0; i<32; i++) miscellaneous[i] = 0;
28326
28327
28328
28329 playing_field_offset=56; // otherwise, red_shift() may go past the bottom of the screen
28330 quakeclk=wavy=0;
28331
28332 //in original Z1, Hero marker vanishes at death.
28333 //code in subscr.cpp, put_passive_subscr checks the following value.
28334 //color 255 is a GUI color, so quest makers shouldn't be using this value.
28335 //Also, subscreen is static after death in Z1.
28336 int32_t tmp_hero_dot = QMisc.colors.hero_dot;
28337 QMisc.colors.hero_dot = 255;
28338 //doesn't work
28339 //scrollbuf is tampered with by draw_screen()
28340 //put_passive_subscr(scrollbuf, &QMisc, 256, passive_subscreen_offset, false, false);//save this and reuse it.
28341 BITMAP *subscrbmp = create_bitmap_ex(8, framebuf->w, framebuf->h);
28342 clear_bitmap(subscrbmp);
28343 put_passive_subscr(subscrbmp, &QMisc, 0, passive_subscreen_offset, false, sspUP);
28344 QMisc.colors.hero_dot = tmp_hero_dot;
28345 */
28346 BITMAP *subscrbmp = create_bitmap_ex(8, framebuf->w, framebuf->h);
28347 clear_bitmap(subscrbmp);
28348 //get rid off all sprites but Hero
28349 guys.clear();
28350 items.clear();
28351 Ewpns.clear();
28352 Lwpns.clear();
28353 Sitems.clear();
28354 chainlinks.clear();
28355 decorations.clear();
28356 Playing = false;
28357
28358 game->set_deaths(zc_min(game->get_deaths()+1,USHRT_MAX));
28359 dir=down;
28360 music_stop();
28361
28362 attackclk=hclk=superman=0;
28363 scriptcoldet = 1;
28364
28365 for(int32_t i=0; i<32; i++) miscellaneous[i] = 0;
28366
28367
28368
28369 playing_field_offset=56; // otherwise, red_shift() may go past the bottom of the screen
28370 quakeclk=wavy=0;
28371
28372 //in original Z1, Hero marker vanishes at death.
28373 //code in subscr.cpp, put_passive_subscr checks the following value.
28374 //color 255 is a GUI color, so quest makers shouldn't be using this value.
28375 //Also, subscreen is static after death in Z1.
28376 int32_t tmp_hero_dot = QMisc.colors.hero_dot;
28377 QMisc.colors.hero_dot = 255;
28378 //doesn't work
28379 //scrollbuf is tampered with by draw_screen()
28380 //put_passive_subscr(scrollbuf, &QMisc, 256, passive_subscreen_offset, false, false);//save this and reuse it.
28381
28382 put_passive_subscr(subscrbmp, &QMisc, 0, passive_subscreen_offset, game->should_show_time(), sspUP);
28383 //Don't forget passive subscreen scripts!
28384 if(get_bit(quest_rules, qr_PASSIVE_SUBSCRIPT_RUNS_WHEN_GAME_IS_FROZEN))
28385 {
28386 script_drawing_commands.Clear(); //We only want draws from this script
28387 if(DMaps[currdmap].passive_sub_script != 0)
28388 ZScriptVersion::RunScript(SCRIPT_PASSIVESUBSCREEN, DMaps[currdmap].passive_sub_script, currdmap);
28389 if(passive_subscreen_waitdraw && DMaps[currdmap].passive_sub_script != 0 && passive_subscreen_doscript != 0)
28390 {
28391 ZScriptVersion::RunScript(SCRIPT_PASSIVESUBSCREEN, DMaps[currdmap].passive_sub_script, currdmap);
28392 passive_subscreen_waitdraw = false;
28393 }
28394 BITMAP* tmp = framebuf;
28395 framebuf = subscrbmp; //Hack; force draws to subscrbmp
28396 do_script_draws(framebuf, tmpscr, 0, playing_field_offset); //Draw the script draws
28397 framebuf = tmp;
28398 script_drawing_commands.Clear(); //Don't let these draws repeat during 'draw_screen()'
28399 }
28400 QMisc.colors.hero_dot = tmp_hero_dot;
28401 bool clearedit = false;
28402 do
28403 {
28404 //if ( player_doscript )
28405 //{
28406 // ZScriptVersion::RunScript(SCRIPT_PLAYER, SCRIPT_PLAYER_WIN, SCRIPT_PLAYER_WIN);
28407 //if ( f ) --f;
28408 // load_control_state(); //goto adv;
28409 //}
28410 //else
28411 //{
28412 // if ( !clearedit )
28413 // {
28414
28415
28416 // clearedit = true;
28417
28418 // }
28419 //}
28420 //else Playing = false;
28421 if(f<254)
28422 {
28423 if(f<=32)
28424 {
28425 hclk=(32-f);
28426 }
28427
28428 if(f>=62 && f<138)
28429 {
28430 switch((f-62)%20)
28431 {
28432 case 0:
28433 dir=right;
28434 break;
28435
28436 case 5:
28437 dir=up;
28438 break;
28439
28440 case 10:
28441 dir=left;
28442 break;
28443
28444 case 15:
28445 dir=down;
28446 break;
28447 }
28448
28449 herostep();
28450 }
28451
28452 if(f>=194 && f<208)
28453 {
28454 if(f==194)
28455 {
28456 action=dying;
28457 FFCore.setHeroAction(dying);
28458 }
28459
28460 extend = 0;
28461 cs = wpnsbuf[spr_death].csets&15;
28462 tile = wpnsbuf[spr_death].tile;
28463 if(!get_bit(quest_rules,qr_HARDCODED_ENEMY_ANIMS))
28464 {
28465 tile += deathfrm;
28466 f = 206;
28467 if(++deathclk >= wpnsbuf[spr_death].speed)
28468 {
28469 deathclk=0;
28470 if(++deathfrm >= wpnsbuf[spr_death].frames)
28471 {
28472 f = 208;
28473 deathfrm = 0;
28474 }
28475 }
28476 }
28477 else if(BSZ)
28478 {
28479 tile += (f-194)/3;
28480 }
28481 else if(f>=204)
28482 {
28483 ++tile;
28484 }
28485 }
28486
28487 if(f==208)
28488 {
28489 if ( dontdraw < 2 ) { dontdraw = 1; }
28490 }
28491 if(get_bit(quest_rules,qr_FADE))
28492 {
28493 if(f < 170)
28494 {
28495 if(f<60)
28496 {
28497 draw_screen(tmpscr);
28498 //reuse our static subscreen
28499 set_clip_rect(framebuf, 0, 0, framebuf->w, framebuf->h);
28500 blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height);
28501 }
28502
28503 if(f==60)
28504 {
28505 red_shift();
28506 create_rgb_table_range(&rgb_table, RAMpal, 208, 239, NULL);
28507 create_zc_trans_table(&trans_table, RAMpal, 128, 128, 128);
28508 memcpy(&trans_table2, &trans_table, sizeof(COLOR_MAP));
28509
28510 for(int32_t q=0; q<PAL_SIZE; q++)
28511 {
28512 trans_table2.data[0][q] = q;
28513 trans_table2.data[q][q] = q;
28514 }
28515 }
28516
28517 if(f>=60 && f<=169)
28518 {
28519 draw_screen(tmpscr);
28520 //reuse our static subscreen
28521 blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height);
28522 red_shift();
28523
28524 }
28525
28526 if(f>=139 && f<=169)//fade from red to black
28527 {
28528 fade_interpolate(RAMpal,black_palette,RAMpal, (f-138)<<1, 224, 255);
28529 create_rgb_table_range(&rgb_table, RAMpal, 208, 239, NULL);
28530 create_zc_trans_table(&trans_table, RAMpal, 128, 128, 128);
28531 memcpy(&trans_table2, &trans_table, sizeof(COLOR_MAP));
28532
28533 for(int32_t q=0; q<PAL_SIZE; q++)
28534 {
28535 trans_table2.data[0][q] = q;
28536 trans_table2.data[q][q] = q;
28537 }
28538
28539 refreshpal=true;
28540 }
28541 }
28542 else //f>=170
28543 {
28544 if(f==170)//make Hero grayish
28545 {
28546 fade_interpolate(RAMpal,black_palette,RAMpal,64, 224, 255);
28547
28548 for(int32_t i=CSET(6); i < CSET(7); i++)
28549 {
28550 int32_t g = (RAMpal[i].r + RAMpal[i].g + RAMpal[i].b)/3;
28551 RAMpal[i] = _RGB(g,g,g);
28552 }
28553
28554 refreshpal = true;
28555 }
28556
28557 //draw only hero. otherwise black layers might cover him.
28558 rectfill(framebuf,0,playing_field_offset,255,167+playing_field_offset,0);
28559 draw(framebuf);
28560 blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height);
28561 }
28562 }
28563 else //!qr_FADE
28564 {
28565 if(f==58)
28566 {
28567 for(int32_t i = 0; i < 96; i++)
28568 tmpscr->cset[i] = 3;
28569
28570 for(int32_t j=0; j<6; j++)
28571 if(tmpscr->layermap[j]>0)
28572 for(int32_t i=0; i<96; i++)
28573 tmpscr2[j].cset[i] = 3;
28574 }
28575
28576 if(f==59)
28577 {
28578 for(int32_t i = 96; i < 176; i++)
28579 tmpscr->cset[i] = 3;
28580
28581 for(int32_t j=0; j<6; j++)
28582 if(tmpscr->layermap[j]>0)
28583 for(int32_t i=96; i<176; i++)
28584 tmpscr2[j].cset[i] = 3;
28585 }
28586
28587 if(f==60)
28588 {
28589 for(int32_t i=0; i<176; i++)
28590 {
28591 tmpscr->cset[i] = 2;
28592 }
28593
28594 for(int32_t j=0; j<6; j++)
28595 if(tmpscr->layermap[j]>0)
28596 for(int32_t i=0; i<176; i++)
28597 tmpscr2[j].cset[i] = 2;
28598
28599 for(int32_t i=1; i<16; i+=3)
28600 {
28601 RAMpal[CSET(2)+i] = NESpal(0x17);
28602 RAMpal[CSET(2)+i+1] = NESpal(0x16);
28603 RAMpal[CSET(2)+i+2] = NESpal(0x26);
28604 }
28605
28606 refreshpal=true;
28607 }
28608
28609 if(f==139)
28610 slide_in_color(0x06);
28611
28612 if(f==149)
28613 slide_in_color(0x07);
28614
28615 if(f==159)
28616 slide_in_color(0x0F);
28617
28618 if(f==169)
28619 {
28620 slide_in_color(0x0F);
28621 slide_in_color(0x0F);
28622 }
28623
28624 if(f==170)
28625 {
28626 for(int32_t i=1; i<16; i+=3)
28627 {
28628 RAMpal[CSET(6)+i] = NESpal(0x10);
28629 RAMpal[CSET(6)+i+1] = NESpal(0x30);
28630 RAMpal[CSET(6)+i+2] = NESpal(0x00);
28631 refreshpal = true;
28632 }
28633 }
28634
28635 if(f < 169)
28636 {
28637 draw_screen(tmpscr);
28638 //reuse our static subscreen
28639 blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height);
28640 }
28641 else
28642 {
28643 //draw only hero. otherwise black layers might cover him.
28644 rectfill(framebuf,0,playing_field_offset,255,167+playing_field_offset,0);
28645 draw(framebuf);
28646 blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height);
28647 }
28648 }
28649 }
28650
28651 else if(f<350)//draw 'GAME OVER' text
28652 {
28653 if(get_bit(quest_rules, qr_INSTANT_RESPAWN) && !get_bit(quest_rules, qr_INSTANT_CONTINUE))
28654 {
28655 Quit = qRELOAD;
28656 skipcont = 1;
28657 clear_bitmap(framebuf);
28658 blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height);
28659 }
28660 else if(!get_bit(quest_rules, qr_INSTANT_RESPAWN) && get_bit(quest_rules, qr_INSTANT_CONTINUE))
28661 {
28662 Quit = qCONT;
28663 skipcont = 1;
28664 clear_bitmap(framebuf);
28665 blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height);
28666 }
28667 else
28668 {
28669 clear_to_color(framebuf,SaveScreenSettings[SAVESC_BACKGROUND]);
28670 blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height);
28671 textout_ex(framebuf,zfont,"GAME OVER",96,playing_field_offset+80,SaveScreenSettings[SAVESC_TEXT],-1);
28672 }
28673 }
28674 else
28675 {
28676 clear_bitmap(framebuf);
28677 }
28678
28679 //SFX... put them all here
28680 switch(f)
28681 {
28682 case 0:
28683 sfx(getHurtSFX(),pan(x.getInt()));
28684 break;
28685 //Death sound.
28686 case 60:
28687 sfx(WAV_SPIRAL);
28688 break;
28689 //Message sound.
28690 case 194:
28691 sfx(WAV_MSG);
28692 break;
28693 }
28694 //adv:
28695 advanceframe(true);
28696 ++f;
28697 //if (!player_doscript ) ++f;
28698 }
28699 while(f<353 && !Quit);
28700
28701 destroy_bitmap(subscrbmp);
28702 action=none; FFCore.setHeroAction(none);
28703 if ( dontdraw < 2 ) { dontdraw=0; }
28704 }
28705
28706
28707 void HeroClass::ganon_intro()
28708 {
28709 /*
28710 ************************
28711 * GANON INTRO SEQUENCE *
28712 ************************
28713 -25 DOT updates
28714 -24 HERO in
28715 0 TRIFORCE overhead - code begins at this point (f == 0)
28716 47 GANON in
28717 58 LIGHT step
28718 68 LIGHT step
28719 78 LIGHT step
28720 255 TRIFORCE out
28721 256 TRIFORCE in
28722 270 TRIFORCE out
28723 271 GANON out, HERO face up
28724 */
28725 loaded_guys=true;
28726 loaditem();
28727
28728 if(game->lvlitems[dlevel]&liBOSS)
28729 {
28730 return;
28731 }
28732
28733 dir=down;
28734 if ( !isSideViewHero() )
28735 {
28736 fall = 0; //Fix midair glitch on holding triforce. -Z
28737 fakefall = 0;
28738 z = 0;
28739 fakez = 0;
28740 }
28741 action=landhold2; FFCore.setHeroAction(landhold2);
28742 holditem=getItemID(itemsbuf,itype_triforcepiece, 1);
28743 //not good, as this only returns the highest level that Hero possesses. -DD
28744 //getHighestLevelOfFamily(game, itemsbuf, itype_triforcepiece, false));
28745
28746 for(int32_t f=0; f<271 && !Quit; f++)
28747 {
28748 if(f==47)
28749 {
28750 music_stop();
28751 stop_sfx(WAV_ROAR);
28752 sfx(WAV_GASP);
28753 sfx(WAV_GANON);
28754 int32_t Id=0;
28755
28756 for(int32_t i=0; i<eMAXGUYS; i++)
28757 {
28758 if(guysbuf[i].flags2&eneflag_ganon)
28759 {
28760 Id=i;
28761 break;
28762 }
28763 }
28764
28765 if(current_item(itype_ring))
28766 {
28767 addenemy(160,96,Id,0);
28768 }
28769 else
28770 {
28771 addenemy(80,32,Id,0);
28772 }
28773 }
28774
28775 if(f==48)
28776 {
28777 lighting(true,true); // Hmm. -L
28778 f += 30;
28779 }
28780
28781 //NES Z1, the triforce vanishes for one frame in two cases
28782 //while still showing Hero's two-handed overhead sprite.
28783 //This should be a Quest Rule for NES Accuracy. -Z
28784 if(f==255 || f==270)
28785 {
28786 holditem=-1;
28787 }
28788
28789 if(f==256)
28790 {
28791 holditem=getItemID(itemsbuf,itype_triforcepiece,1);
28792 }
28793
28794 draw_screen(tmpscr);
28795 advanceframe(true);
28796
28797 if(rSbtn())
28798 {
28799 conveyclk=3;
28800 int32_t tmp_subscr_clk = frame;
28801 dosubscr(&QMisc);
28802 newscr_clk += frame - tmp_subscr_clk;
28803 }
28804
28805 }
28806
28807 action=none; FFCore.setHeroAction(none);
28808 dir=up;
28809
28810 if((!getmapflag() || (tmpscr->flags9&fBELOWRETURN)) && (tunes[MAXMIDIS-1].data))
28811 jukebox(MAXMIDIS-1);
28812 else
28813 playLevelMusic();
28814
28815 currcset=DMaps[currdmap].color;
28816 if (get_bit(quest_rules, qr_GANONINTRO) )
28817 {
28818 dointro();
28819 //Yes, I checked. This is literally in 2.10 (minus this if statement of course).
28820 //I have no clue why it's here; Literally the only difference between dointro in 2.10 and dointro in this version is an 'else' that sets introclk and intropos to 74.
28821 //I have no idea what was going through the original devs heads and I'm extremely worried I'm missing something, cause at first glance this looks like
28822 //a hack solution to an underlying bug, but no! There's just a fucking dointro() call in older versions and I don't know *why*. -Deedee
28823 }
28824 //dointro(); //This is likely what causes Ganon Rooms to repeat the DMap intro.
28825 //I suppose it is to allow the user to make Gaanon rooms have their own dialogue, if they are
28826 //on a different DMap.
28827 //~ Otherwise, why is it here?! -Z
28828
28829
28830 //if ( !(DMaps[currdmap].flags&dmfALWAYSMSG) ) { dointro(); } //This is likely what causes Ganon Rooms to repeat the DMap intro.
28831 //If we try it this way: The dmap flag /always display intro string/ is probably why James had this issue.
28832
28833 //The only fix that I can think of, off the top of me head, is either a QR or a Screen Flag to disable the intro text.
28834 //Users who use that dmap rule should put ganons room on its own DMap! -Z
28835 cont_sfx(WAV_ROAR);
28836 }
28837
28838 void HeroClass::win_game()
28839 {
28840 replay_step_comment("win_game");
28841 Playing=Paused=false;
28842 action=won; FFCore.setHeroAction(won);
28843 Quit=qWON;
28844 hclk=0;
28845 x = 136;
28846 y = (isdungeon() && currscr<128) ? 75 : 73;
28847 z = fakez = fall = fakefall = spins = 0;
28848 dir=left;
28849 }
28850
28851 25 void HeroClass::reset_swordcharge()
28852 {
28853 25 charging=spins=tapping=0;
28854 25 }
28855
28856 35 void HeroClass::reset_hookshot()
28857 {
28858
7/12
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 34 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 34 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 34 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 34 times.
35 if(action!=walking && action!=rafting && action!=landhold1 && action!=landhold2 && action!=sidewaterhold1 && action!=sidewaterhold2)
28859 {
28860 34 action=none; FFCore.setHeroAction(none);
28861 34 }
28862
28863 35 hookshot_frozen=false;
28864 35 hookshot_used=false;
28865 35 pull_hero=false;
28866 35 hs_fix=false;
28867 35 switchhookclk = switchhookmaxtime = switchhookstyle = switchhookarg = 0;
28868 35 switch_hooked = false;
28869
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if(switching_object)
28870 switching_object->switch_hooked = false;
28871 35 switching_object = NULL;
28872 35 hooked_combopos = -1;
28873 35 switchhook_cost_item = -1;
28874 35 hooked_layerbits = 0;
28875
2/2
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 35 times.
280 for(auto q = 0; q < 7; ++q)
28876 245 hooked_undercombos[q] = -1;
28877 35 Lwpns.del(Lwpns.idFirst(wHSHandle));
28878 35 Lwpns.del(Lwpns.idFirst(wHookshot));
28879 35 chainlinks.clear();
28880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 int32_t index=directItem>-1 ? directItem : current_item_id(hs_switcher ? itype_switchhook : itype_hookshot);
28881 35 hs_switcher = false;
28882
28883
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if(index>=0)
28884 {
28885 stop_sfx(itemsbuf[index].usesound);
28886 }
28887
28888 35 hs_xdist=0;
28889 35 hs_ydist=0;
28890 35 }
28891
28892
28893 154 bool HeroClass::can_deploy_ladder()
28894 {
28895
1/2
✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
308 bool ladderallowed = ((!get_bit(quest_rules,qr_LADDERANYWHERE) && tmpscr->flags&fLADDER) || isdungeon()
28896 || (get_bit(quest_rules,qr_LADDERANYWHERE) && !(tmpscr->flags&fLADDER)));
28897
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 462 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
462 return (current_item_id(itype_ladder)>-1 && ladderallowed && !ilswim && z==0 && fakez==0 &&
28898 (!isSideViewHero() || on_sideview_solid_oldpos(x,y,old_x,old_y)));
28899 }
28900
28901 1902 void HeroClass::reset_ladder()
28902 {
28903 1902 ladderx=laddery=0;
28904 1902 }
28905
28906 bool is_conveyor(int32_t type);
28907 int32_t get_conveyor(int32_t x, int32_t y);
28908
28909 1888 void HeroClass::check_conveyor()
28910 {
28911 1888 ++newconveyorclk;
28912
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if (newconveyorclk < 0) newconveyorclk = 0;
28913
28914
9/18
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1888 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1888 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1888 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1888 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1888 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1888 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1888 times.
✗ Branch 17 not taken.
1888 if(action==casting||action==sideswimcasting||action==drowning || action==sidedrowning||action==lavadrowning||inlikelike||pull_hero||((z>0||fakez>0) && !(tmpscr->flags2&fAIRCOMBOS)))
28915 {
28916 is_conveyor_stunned = 0;
28917 return;
28918 }
28919
28920 1888 WalkflagInfo info;
28921 int32_t xoff,yoff;
28922 1888 zfix deltax(0), deltay(0);
28923 1888 int32_t cmbid = get_conveyor(x+7,y+(bigHitbox?8:12));
28924
2/2
✓ Branch 0 taken 1260 times.
✓ Branch 1 taken 628 times.
1888 if(cmbid < 0)
28925 {
28926
1/2
✓ Branch 0 taken 1260 times.
✗ Branch 1 not taken.
1260 if (conveyclk <= 0) is_on_conveyor=false;
28927 1260 return;
28928 }
28929 628 newcombo const* cmb = &combobuf[cmbid];
28930 628 auto pos = COMBOPOS(x+7,y+(bigHitbox?8:12));
28931 628 bool custom_spd = (cmb->usrflags&cflag2);
28932
2/4
✓ Branch 0 taken 628 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 628 times.
✗ Branch 3 not taken.
628 if(custom_spd || conveyclk<=0) //!DIMITODO: let player be on multiple conveyors at once
28933 {
28934 628 int32_t ctype=cmb->type;
28935
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 628 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
628 auto rate = custom_spd ? zc_max(cmb->attribytes[0], 1) : 3;
28936
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 628 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
628 if(custom_spd && (newconveyorclk % rate)) return;
28937
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 628 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
628 if((cmb->usrflags&cflag5) && HasHeavyBoots())
28938 return;
28939 628 is_on_conveyor=false;
28940 628 is_conveyor_stunned=0;
28941
28942 628 deltax=combo_class_buf[ctype].conveyor_x_speed;
28943 628 deltay=combo_class_buf[ctype].conveyor_y_speed;
28944
28945
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 628 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
628 if (is_conveyor(ctype) && custom_spd)
28946 {
28947 deltax = zslongToFix(cmb->attributes[0]);
28948 deltay = zslongToFix(cmb->attributes[1]);
28949 }
28950
28951
3/8
✓ Branch 0 taken 628 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 628 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 628 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
628 if((deltax==0&&deltay==0)&&(isSideViewHero() && on_sideview_solid_oldpos(x,y,old_x,old_y)))
28952 {
28953 cmbid = MAPCOMBO(x+8,y+16);
28954 cmb = &combobuf[cmbid];
28955 custom_spd = cmb->usrflags&cflag2;
28956 ctype=(cmb->type);
28957 deltax=combo_class_buf[ctype].conveyor_x_speed;
28958 deltay=combo_class_buf[ctype].conveyor_y_speed;
28959 if ((deltax != 0 || deltay != 0) && custom_spd)
28960 {
28961 deltax = zslongToFix(cmb->attributes[0]);
28962 deltay = zslongToFix(cmb->attributes[1]);
28963 }
28964 }
28965
28966
2/4
✓ Branch 0 taken 628 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 628 times.
628 if(deltax!=0||deltay!=0)
28967 {
28968 is_on_conveyor=true;
28969 }
28970 628 else return;
28971
28972 bool movedx = false, movedy = false;
28973 if(cmb->usrflags&cflag4) //Smart corners
28974 {
28975 if(deltay<0)
28976 {
28977 info = walkflag(x,y+8-(bigHitbox*8)-2,2,up);
28978 execute(info);
28979
28980 if(!info.isUnwalkable())
28981 {
28982 movedy = true;
28983 zfix step(0);
28984
28985 if((DrunkRight()||DrunkLeft())&&dir!=left&&dir!=right&&!(diagonalMovement||NO_GRIDLOCK))
28986 {
28987 while(step<(abs(deltay)*(isSideViewHero()?2:1)))
28988 {
28989 yoff=int32_t(y-step)&7;
28990
28991 if(!yoff) break;
28992
28993 step++;
28994 }
28995 }
28996 else
28997 {
28998 step=abs(deltay);
28999 }
29000
29001 y=y-step;
29002 hs_starty-=step.getInt();
29003
29004 for(int32_t j=0; j<chainlinks.Count(); j++)
29005 {
29006 chainlinks.spr(j)->y-=step;
29007 }
29008
29009 if(Lwpns.idFirst(wHookshot)>-1)
29010 {
29011 Lwpns.spr(Lwpns.idFirst(wHookshot))->y-=step;
29012 }
29013
29014 if(Lwpns.idFirst(wHSHandle)>-1)
29015 {
29016 Lwpns.spr(Lwpns.idFirst(wHSHandle))->y-=step;
29017 }
29018 }
29019 }
29020 else if(deltay>0)
29021 {
29022 info = walkflag(x,y+15+2,2,down);
29023 execute(info);
29024
29025 if(!info.isUnwalkable())
29026 {
29027 movedy = true;
29028 zfix step(0);
29029
29030 if((DrunkRight()||DrunkLeft())&&dir!=left&&dir!=right&&!(diagonalMovement||NO_GRIDLOCK))
29031 {
29032 while(step<abs(deltay))
29033 {
29034 yoff=int32_t(y+step)&7;
29035
29036 if(!yoff) break;
29037
29038 step++;
29039 }
29040 }
29041 else
29042 {
29043 step=abs(deltay);
29044 }
29045
29046 y=y+step;
29047 hs_starty+=step.getInt();
29048
29049 for(int32_t j=0; j<chainlinks.Count(); j++)
29050 {
29051 chainlinks.spr(j)->y+=step;
29052 }
29053
29054 if(Lwpns.idFirst(wHookshot)>-1)
29055 {
29056 Lwpns.spr(Lwpns.idFirst(wHookshot))->y+=step;
29057 }
29058
29059 if(Lwpns.idFirst(wHSHandle)>-1)
29060 {
29061 Lwpns.spr(Lwpns.idFirst(wHSHandle))->y+=step;
29062 }
29063 }
29064 }
29065
29066 if(deltax<0)
29067 {
29068 info = walkflag(x-int32_t(lsteps[x.getInt()&7]),y+8-(bigHitbox ? 8 : 0),1,left);
29069 execute(info);
29070
29071 if(!info.isUnwalkable())
29072 {
29073 movedx = true;
29074 zfix step(0);
29075
29076 if((DrunkUp()||DrunkDown())&&dir!=up&&dir!=down&&!(diagonalMovement||NO_GRIDLOCK))
29077 {
29078 while(step<abs(deltax))
29079 {
29080 xoff=int32_t(x-step)&7;
29081
29082 if(!xoff) break;
29083
29084 step++;
29085 }
29086 }
29087 else
29088 {
29089 step=abs(deltax);
29090 }
29091
29092 x=x-step;
29093 hs_startx-=step.getInt();
29094
29095 for(int32_t j=0; j<chainlinks.Count(); j++)
29096 {
29097 chainlinks.spr(j)->x-=step;
29098 }
29099
29100 if(Lwpns.idFirst(wHookshot)>-1)
29101 {
29102 Lwpns.spr(Lwpns.idFirst(wHookshot))->x-=step;
29103 }
29104
29105 if(Lwpns.idFirst(wHSHandle)>-1)
29106 {
29107 Lwpns.spr(Lwpns.idFirst(wHSHandle))->x-=step;
29108 }
29109 }
29110 }
29111 else if(deltax>0)
29112 {
29113 info = walkflag(x+15+2,y+8-(bigHitbox ? 8 : 0),1,right);
29114 execute(info);
29115
29116 if(!info.isUnwalkable())
29117 {
29118 movedx = true;
29119 zfix step(0);
29120
29121 if((DrunkUp()||DrunkDown())&&dir!=up&&dir!=down&&!(diagonalMovement||NO_GRIDLOCK))
29122 {
29123 while(step<abs(deltax))
29124 {
29125 xoff=int32_t(x+step)&7;
29126
29127 if(!xoff) break;
29128
29129 step++;
29130 }
29131 }
29132 else
29133 {
29134 step=abs(deltax);
29135 }
29136
29137 x=x+step;
29138 hs_startx+=step.getInt();
29139
29140 for(int32_t j=0; j<chainlinks.Count(); j++)
29141 {
29142 chainlinks.spr(j)->x+=step;
29143 }
29144
29145 if(Lwpns.idFirst(wHookshot)>-1)
29146 {
29147 Lwpns.spr(Lwpns.idFirst(wHookshot))->x+=step;
29148 }
29149
29150 if(Lwpns.idFirst(wHSHandle)>-1)
29151 {
29152 Lwpns.spr(Lwpns.idFirst(wHSHandle))->x+=step;
29153 }
29154 }
29155 }
29156 if(deltax && !movedx)
29157 y = COMBOY(pos);
29158 if(deltay && !movedy)
29159 x = COMBOX(pos);
29160 }
29161 if(!movedy)
29162 {
29163 if(deltay<0)
29164 {
29165 info = walkflag(x,y+8-(bigHitbox*8)-2,2,up);
29166 execute(info);
29167
29168 if(!info.isUnwalkable())
29169 {
29170 movedy = true;
29171 zfix step(0);
29172
29173 if((DrunkRight()||DrunkLeft())&&dir!=left&&dir!=right&&!(diagonalMovement||NO_GRIDLOCK))
29174 {
29175 while(step<(abs(deltay)*(isSideViewHero()?2:1)))
29176 {
29177 yoff=int32_t(y-step)&7;
29178
29179 if(!yoff) break;
29180
29181 step++;
29182 }
29183 }
29184 else
29185 {
29186 step=abs(deltay);
29187 }
29188
29189 y=y-step;
29190 hs_starty-=step.getInt();
29191
29192 for(int32_t j=0; j<chainlinks.Count(); j++)
29193 {
29194 chainlinks.spr(j)->y-=step;
29195 }
29196
29197 if(Lwpns.idFirst(wHookshot)>-1)
29198 {
29199 Lwpns.spr(Lwpns.idFirst(wHookshot))->y-=step;
29200 }
29201
29202 if(Lwpns.idFirst(wHSHandle)>-1)
29203 {
29204 Lwpns.spr(Lwpns.idFirst(wHSHandle))->y-=step;
29205 }
29206 }
29207 else checkdamagecombos(x,y+8-(bigHitbox ? 8 : 0)-2);
29208 }
29209 else if(deltay>0)
29210 {
29211 info = walkflag(x,y+15+2,2,down);
29212 execute(info);
29213
29214 if(!info.isUnwalkable())
29215 {
29216 movedy = true;
29217 zfix step(0);
29218
29219 if((DrunkRight()||DrunkLeft())&&dir!=left&&dir!=right&&!(diagonalMovement||NO_GRIDLOCK))
29220 {
29221 while(step<abs(deltay))
29222 {
29223 yoff=int32_t(y+step)&7;
29224
29225 if(!yoff) break;
29226
29227 step++;
29228 }
29229 }
29230 else
29231 {
29232 step=abs(deltay);
29233 }
29234
29235 y=y+step;
29236 hs_starty+=step.getInt();
29237
29238 for(int32_t j=0; j<chainlinks.Count(); j++)
29239 {
29240 chainlinks.spr(j)->y+=step;
29241 }
29242
29243 if(Lwpns.idFirst(wHookshot)>-1)
29244 {
29245 Lwpns.spr(Lwpns.idFirst(wHookshot))->y+=step;
29246 }
29247
29248 if(Lwpns.idFirst(wHSHandle)>-1)
29249 {
29250 Lwpns.spr(Lwpns.idFirst(wHSHandle))->y+=step;
29251 }
29252 }
29253 else checkdamagecombos(x,y+15);
29254 }
29255 }
29256 if(!movedx)
29257 {
29258 if(deltax<0)
29259 {
29260 info = walkflag(x-int32_t(lsteps[x.getInt()&7]),y+8-(bigHitbox ? 8 : 0),1,left);
29261 execute(info);
29262
29263 if(!info.isUnwalkable())
29264 {
29265 movedx = true;
29266 zfix step(0);
29267
29268 if((DrunkUp()||DrunkDown())&&dir!=up&&dir!=down&&!(diagonalMovement||NO_GRIDLOCK))
29269 {
29270 while(step<abs(deltax))
29271 {
29272 xoff=int32_t(x-step)&7;
29273
29274 if(!xoff) break;
29275
29276 step++;
29277 }
29278 }
29279 else
29280 {
29281 step=abs(deltax);
29282 }
29283
29284 x=x-step;
29285 hs_startx-=step.getInt();
29286
29287 for(int32_t j=0; j<chainlinks.Count(); j++)
29288 {
29289 chainlinks.spr(j)->x-=step;
29290 }
29291
29292 if(Lwpns.idFirst(wHookshot)>-1)
29293 {
29294 Lwpns.spr(Lwpns.idFirst(wHookshot))->x-=step;
29295 }
29296
29297 if(Lwpns.idFirst(wHSHandle)>-1)
29298 {
29299 Lwpns.spr(Lwpns.idFirst(wHSHandle))->x-=step;
29300 }
29301 }
29302 else checkdamagecombos(x-int32_t(lsteps[x.getInt()&7]),y+8-(bigHitbox ? 8 : 0));
29303 }
29304 else if(deltax>0)
29305 {
29306 info = walkflag(x+15+2,y+8-(bigHitbox ? 8 : 0),1,right);
29307 execute(info);
29308
29309 if(!info.isUnwalkable())
29310 {
29311 movedx = true;
29312 zfix step(0);
29313
29314 if((DrunkUp()||DrunkDown())&&dir!=up&&dir!=down&&!(diagonalMovement||NO_GRIDLOCK))
29315 {
29316 while(step<abs(deltax))
29317 {
29318 xoff=int32_t(x+step)&7;
29319
29320 if(!xoff) break;
29321
29322 step++;
29323 }
29324 }
29325 else
29326 {
29327 step=abs(deltax);
29328 }
29329
29330 x=x+step;
29331 hs_startx+=step.getInt();
29332
29333 for(int32_t j=0; j<chainlinks.Count(); j++)
29334 {
29335 chainlinks.spr(j)->x+=step;
29336 }
29337
29338 if(Lwpns.idFirst(wHookshot)>-1)
29339 {
29340 Lwpns.spr(Lwpns.idFirst(wHookshot))->x+=step;
29341 }
29342
29343 if(Lwpns.idFirst(wHSHandle)>-1)
29344 {
29345 Lwpns.spr(Lwpns.idFirst(wHSHandle))->x+=step;
29346 }
29347 }
29348 else checkdamagecombos(x+15+2,y+8-(bigHitbox ? 8 : 0));
29349 }
29350 }
29351 if(movedx || movedy)
29352 {
29353 if(cmb->usrflags&cflag1)
29354 is_conveyor_stunned = rate;
29355 if(cmb->usrflags&cflag3)
29356 {
29357 if(abs(deltax) > abs(deltay))
29358 dir = (deltax > 0) ? right : left;
29359 else dir = (deltay > 0) ? down : up;
29360 }
29361 }
29362 }
29363 1888 }
29364
29365 void HeroClass::setNayrusLoveShieldClk(int32_t newclk)
29366 {
29367 NayrusLoveShieldClk=newclk;
29368
29369 if(decorations.idCount(dNAYRUSLOVESHIELD)==0)
29370 {
29371 decoration *dec;
29372 decorations.add(new dNayrusLoveShield(HeroX(), HeroY(), dNAYRUSLOVESHIELD, 0));
29373 decorations.spr(decorations.Count()-1)->misc=0;
29374 decorations.add(new dNayrusLoveShield(HeroX(), HeroY(), dNAYRUSLOVESHIELD, 0));
29375 dec=(decoration *)decorations.spr(decorations.Count()-1);
29376 decorations.spr(decorations.Count()-1)->misc=1;
29377 }
29378 }
29379
29380 19 int32_t HeroClass::getNayrusLoveShieldClk()
29381 {
29382 19 return NayrusLoveShieldClk;
29383 }
29384
29385 int32_t HeroClass::getHoverClk()
29386 {
29387 return hoverclk;
29388 }
29389
29390 int32_t HeroClass::getHoldClk()
29391 {
29392 return holdclk;
29393 }
29394
29395 1523 int32_t HeroClass::getLastLensID(){
29396 1523 return last_lens_id;
29397 }
29398
29399 void HeroClass::setLastLensID(int32_t p_item){
29400 last_lens_id = p_item;
29401 }
29402
29403 14818 bool HeroClass::getOnSideviewLadder()
29404 {
29405 14818 return on_sideview_ladder;
29406 }
29407
29408 void HeroClass::setOnSideviewLadder(bool val)
29409 {
29410 if(val)
29411 {
29412 fall = fakefall = hoverclk = jumping = 0;
29413 hoverflags = 0;
29414 inair = false;
29415 }
29416 on_sideview_ladder = val;
29417 }
29418
29419 457 bool HeroClass::canSideviewLadder(bool down)
29420 {
29421
1/2
✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
457 if(!isSideViewHero()) return false;
29422 if(jumping < 0) return false;
29423 if(down && get_bit(quest_rules, qr_DOWN_DOESNT_GRAB_LADDERS))
29424 {
29425 bool onSolid = on_sideview_solid_oldpos(x,y,old_x,old_y,true);
29426 return ((isSVLadder(x+4,y+16) && (!isSVLadder(x+4,y)||onSolid)) || (isSVLadder(x+12,y+16) && (!isSVLadder(x+12,y)||onSolid)));
29427 }
29428 //Are you presently able to climb a sideview ladder?
29429 //x+4 / +12 are the offsets used for detecting a platform below you in sideview
29430 //y+0 checks your top-half for large hitbox; y+8 for small
29431 //y+15 checks if you are on one at all. This is necessary so you don't just fall off before reaching the top.
29432 //y+16 check is for going down onto a ladder you are standing on.
29433 return (isSVLadder(x+4,y+(bigHitbox?0:8)) || isSVLadder(x+12,y+(bigHitbox?0:8)))
29434 || isSVLadder(x+4,y+15) || isSVLadder(x+12,y+15)
29435 || (down && (isSVLadder(x+4,y+16) || isSVLadder(x+12,y+16)));
29436 457 }
29437
29438 bool HeroClass::canSideviewLadderRemote(int32_t wx, int32_t wy, bool down)
29439 {
29440 if(!isSideViewHero()) return false;
29441 if(jumping < 0) return false;
29442 if(down && get_bit(quest_rules, qr_DOWN_DOESNT_GRAB_LADDERS))
29443 {
29444 bool onSolid = on_sideview_solid_oldpos(x,y,old_x,old_y,true);
29445 return ((isSVLadder(wx+4,wy+16) && (!isSVLadder(wx+4,wy)||onSolid)) || (isSVLadder(wx+12,wy+16) && (!isSVLadder(wx+12,wy)||onSolid)));
29446 }
29447 //Are you presently able to climb a sideview ladder?
29448 //x+4 / +12 are the offsets used for detecting a platform below you in sideview
29449 //y+0 checks your top-half for large hitbox; y+8 for small
29450 //y+15 checks if you are on one at all. This is necessary so you don't just fall off before reaching the top.
29451 //y+16 check is for going down onto a ladder you are standing on.
29452 return (isSVLadder(wx+4,wy+(bigHitbox?0:8)) || isSVLadder(wx+12,wy+(bigHitbox?0:8)))
29453 || isSVLadder(wx+4,wy+15) || isSVLadder(wx+12,wy+15)
29454 || (down && (isSVLadder(wx+4,wy+16) || isSVLadder(wx+12,wy+16)));
29455 }
29456
29457 1033 void HeroClass::execute(HeroClass::WalkflagInfo info)
29458 {
29459 1033 int32_t flags = info.getFlags();
29460
29461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1033 times.
1033 if(flags & WalkflagInfo::CLEARILSWIM)
29462 ilswim =false;
29463
1/2
✓ Branch 0 taken 1033 times.
✗ Branch 1 not taken.
1033 else if(flags & WalkflagInfo::SETILSWIM)
29464 ilswim = true;
29465
29466
1/2
✓ Branch 0 taken 1033 times.
✗ Branch 1 not taken.
1033 if(flags & WalkflagInfo::CLEARCHARGEATTACK)
29467 {
29468 charging = 0;
29469 attackclk = 0;
29470 }
29471
29472
1/2
✓ Branch 0 taken 1033 times.
✗ Branch 1 not taken.
1033 if(flags & WalkflagInfo::SETDIR)
29473 {
29474 dir = info.getDir();
29475 }
29476
29477
1/2
✓ Branch 0 taken 1033 times.
✗ Branch 1 not taken.
1033 if(flags & WalkflagInfo::SETHOPCLK)
29478 {
29479 hopclk = info.getHopClk();
29480 }
29481
29482
1/2
✓ Branch 0 taken 1033 times.
✗ Branch 1 not taken.
1033 if(flags & WalkflagInfo::SETHOPDIR)
29483 {
29484 hopdir = info.getHopDir();
29485 }
29486
29487 1033 }
29488
29489 1989 HeroClass::WalkflagInfo HeroClass::WalkflagInfo::operator ||(HeroClass::WalkflagInfo other)
29490 {
29491 1989 HeroClass::WalkflagInfo ret;
29492 1989 ret.newhopclk = newhopclk;
29493 1989 ret.newdir = newdir;
29494
2/2
✓ Branch 0 taken 1561 times.
✓ Branch 1 taken 428 times.
1989 ret.newhopdir = (other.newhopdir >-1 ? other.newhopdir : newhopdir);
29495
29496 1989 int32_t flags1 = (flags & ~UNWALKABLE) & (other.flags & ~UNWALKABLE);
29497 1989 int32_t flags2 = (flags & UNWALKABLE) | (other.flags & UNWALKABLE);
29498 1989 ret.flags = flags1 | flags2;
29499 1989 return ret;
29500 }
29501
29502 HeroClass::WalkflagInfo HeroClass::WalkflagInfo::operator &&(HeroClass::WalkflagInfo other)
29503 {
29504 HeroClass::WalkflagInfo ret;
29505 ret.newhopclk = newhopclk;
29506 ret.newdir = newdir;
29507 ret.newhopdir = (other.newhopdir >-1 ? other.newhopdir : newhopdir);
29508
29509 ret.flags = flags & other.flags;
29510 return ret;
29511 }
29512
29513 HeroClass::WalkflagInfo HeroClass::WalkflagInfo::operator !()
29514 {
29515 HeroClass::WalkflagInfo ret;
29516 ret.newhopclk = newhopclk;
29517 ret.newdir = newdir;
29518 ret.newhopdir = newhopdir;
29519
29520 ret.flags = flags ^ UNWALKABLE;
29521 return ret;
29522 }
29523
29524 void HeroClass::explode(int32_t type)
29525 {
29526 static int32_t tempx, tempy;
29527 static byte herotilebuf[256];
29528 int32_t ltile=0;
29529 int32_t lflip=0;
29530 bool shieldModify=true;
29531 unpack_tile(newtilebuf, tile, flip, true);
29532 memcpy(herotilebuf, unpackbuf, 256);
29533 tempx=Hero.getX();
29534 tempy=Hero.getY();
29535 for(int32_t i=0; i<16; ++i)
29536 {
29537 for(int32_t j=0; j<16; ++j)
29538 {
29539 if(herotilebuf[i*16+j])
29540 {
29541 if(type==0) // Twilight
29542 {
29543 particles.add(new pTwilight(Hero.getX()+j, Hero.getY()-Hero.getZ()+i, 5, 0, 0, (zc_oldrand()%8)+i*4));
29544 int32_t k=particles.Count()-1;
29545 particle *p = (particles.at(k));
29546 p->step=3;
29547 }
29548 else if(type ==1) // Sands of Hours
29549 {
29550 particles.add(new pTwilight(Hero.getX()+j, Hero.getY()-Hero.getZ()+i, 5, 1, 2, (zc_oldrand()%16)+i*2));
29551 int32_t k=particles.Count()-1;
29552 particle *p = (particles.at(k));
29553 p->step=4;
29554
29555 if(zc_oldrand()%10 < 2)
29556 {
29557 p->color=1;
29558 p->cset=0;
29559 }
29560 }
29561 else
29562 {
29563 particles.add(new pFaroresWindDust(Hero.getX()+j, Hero.getY()-Hero.getZ()+i, 5, 6, herotilebuf[i*16+j], zc_oldrand()%96));
29564
29565 int32_t k=particles.Count()-1;
29566 particle *p = (particles.at(k));
29567 p->angular=true;
29568 p->angle=zc_oldrand();
29569 p->step=(((double)j)/8);
29570 p->yofs=Hero.getYOfs();
29571 }
29572 }
29573 }
29574 }
29575 }
29576
29577 void HeroClass::SetSwim()
29578 {
29579 if (CanSideSwim())
29580 {
29581 if (action != sideswimattacking && action != attacking) {action=sideswimming; FFCore.setHeroAction(sideswimming);}
29582 else {action=sideswimattacking; FFCore.setHeroAction(sideswimattacking);}
29583 if (get_bit(quest_rules,qr_SIDESWIMDIR) && spins <= 0 && dir != left && dir != right) dir = sideswimdir;
29584 }
29585 else {action=swimming; FFCore.setHeroAction(swimming);}
29586 }
29587
29588 17 void HeroClass::SetAttack()
29589 {
29590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (IsSideSwim()) {action=sideswimattacking; FFCore.setHeroAction(sideswimattacking);}
29591 17 else {action=attacking; FFCore.setHeroAction(attacking);}
29592 17 }
29593
29594 15033 bool HeroClass::IsSideSwim()
29595 {
29596
6/12
✓ Branch 0 taken 15033 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15033 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15033 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15033 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 15033 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 15033 times.
15033 return (action==sideswimming || action==sideswimhit || action == sideswimattacking || action == sidewaterhold1 || action == sidewaterhold2 || action == sideswimcasting || action == sideswimfreeze);
29597 }
29598
29599 478 bool HeroClass::CanSideSwim()
29600 {
29601
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 return (isSideViewHero() && get_bit(quest_rules,qr_SIDESWIM));
29602 }
29603
29604 1243 int32_t HeroClass::getTileModifier()
29605 {
29606 1243 return item_tile_mod() + bunny_tile_mod();
29607 }
29608 void HeroClass::setImmortal(int32_t nimmortal)
29609 {
29610 immortal = nimmortal;
29611 }
29612 void HeroClass::kill(bool bypassFairy)
29613 {
29614 dying_flags = DYING_FORCED | (bypassFairy ? DYING_NOREV : 0);
29615 }
29616 3776 bool HeroClass::sideview_mode() const
29617 {
29618
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3776 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3776 return isSideViewHero() && (moveflags & FLAG_OBEYS_GRAV) && !toogam;
29619 }
29620 bool HeroClass::is_unpushable() const
29621 {
29622 return toogam;
29623 }
29624 /*** end of hero.cpp ***/
29625
29626
29627
29628
29629